题解 未来

传送门

先设法构造一个 \(f(a, b)=a\oplus b\)
找性质的话可以画表格
\(f(a, b)=-(a+b)\pmod 3\)

于是一次操作为 \(f_i=-(f_i+f_{(i+1) \bmod n})\pmod 3\)
于是可以卷积处理但我不会循环卷积啊
发现系数可以用组合数表示,有

\[ans_i=\sum\limits_{j=0}^n\binom{m}{j}a_{(i+j)\bmod n} \]

又发现这里的组合数是 \(\bmod 3\) 意义下的
我会 Lucas 定理!好像没有什么用
想清楚我们在干什么:这相当于循环卷积,所以我们可以分组做
我们一共要走 \(m\) 步,我们将其分为 \(\sum 3^{m_i}\) 个部分(若 m 在三进制下这一位为 2 则加两次)
这样每一步的式子变成了

\[ans_i=\sum\limits_{j=0}^n\binom{3^{m_k}}{j}a_{(i+j)\bmod n} \]

那么仅在 \(j=0\)\(j=3^{m_k}\) 时转移是有意义的
这样就大大减少了需要枚举的状态
最终复杂度 \(O(n\log m)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 500010
#define ll long long
#define int long long
#define ull unsigned long long

int n, m;
char s[N], t[N], tr[255][255];

void tran() {
	for (int i=0; i<n; ++i) t[i]=tr[s[i]][s[(i+1)%n]];
	for (int i=0; i<n; ++i) s[i]=t[i];
}

namespace force{
	char t[2][N], now;
	char mp1[255], mp2[3], tr[3][3];
	void tran() {
		// for (int i=0; i<n; ++i) t[i]=tr[s[i]][s[(i+1)%n]];
		// for (int i=0; i<n; ++i) s[i]=t[i];
		for (signed i=0; i<n-1; ++i) t[now^1][i]=tr[t[now][i]][t[now][i+1]];
		t[now^1][n-1]=tr[t[now][n-1]][t[now][0]];
		now^=1;
	}
	void solve() {
		mp1['r']=0; mp1['g']=1; mp1['b']=2;
		mp2[0]='r'; mp2[1]='g'; mp2[2]='b';
		tr[mp1['r']][mp1['r']]=mp1['r'];
		tr[mp1['g']][mp1['g']]=mp1['g'];
		tr[mp1['b']][mp1['b']]=mp1['b'];
		tr[mp1['r']][mp1['g']]=tr[mp1['g']][mp1['r']]=mp1['b'];
		tr[mp1['r']][mp1['b']]=tr[mp1['b']][mp1['r']]=mp1['g'];
		tr[mp1['g']][mp1['b']]=tr[mp1['b']][mp1['g']]=mp1['r'];
		for (int i=0; i<n; ++i) t[now][i]=mp1[s[i]];
		for (int i=1; i<=m; ++i) tran();
		for (int i=0; i<n; ++i) s[i]=mp2[t[now][i]];
		printf("%s\n", s);
	}
}

namespace task1{
	char tem[N], bkp[N];
	bool issame() {
		for (int i=0; i<n; ++i) if (s[i]!=tem[i]) return 0;
		return 1;
	}
	bool allsame() {
		for (int i=0; i<n; ++i) if (s[i]!=s[0]) return 0;
		return 1;
	}
	void solve() {
		for (int i=0; i<n; ++i) tem[(i+1)%n]=s[i], bkp[i]=s[i];
		int loop=0;
		for (; !issame()&&!allsame(); ++loop) tran(); //, cout<<s<<' '<<tem<<endl;
		if (allsame()) {
			m=min(m, loop);
			for (int i=0; i<n; ++i) s[i]=bkp[i];
			force::solve();
			exit(0);
		}
		// cout<<"loop: "<<loop<<endl;
		int dlt=(m/loop)%n;
		// cout<<"dlt: "<<dlt<<endl;
		for (int i=0; i<n; ++i) s[i]=bkp[i];
		for (int i=0; i<n; ++i) tem[(i+dlt)%n]=s[i];
		for (int i=0; i<n; ++i) s[i]=tem[i];
		for (int i=1; i<=m%loop; ++i) tran();
		printf("%s\n", s);
	}
}

namespace task{
	ll ans[N], tem[N];
	void solve() {
		for (int i=0; i<n; ++i) s[i]=(s[i]=='r')?0:(s[i]=='g'?1:2);
		while (m) {
			int now=1;
			while (now*3<=m) now*=3;
			for (; m>=now; m-=now) {
				for (int i=0; i<n; ++i) tem[i]=((-(s[i]+s[(i+now)%n]))%3+3)%3;
				for (int i=0; i<n; ++i) s[i]=tem[i];
			}
		}
		for (int i=0; i<n; ++i) s[i]=(s[i]==0)?'r':(s[i]==1?'g':'b');
		printf("%s\n", s);
	}
}

signed main()
{
	freopen("future.in", "r", stdin);
	freopen("future.out", "w", stdout);
	scanf("%lld%lld%s", &n, &m, s);

	// freopen("1.in", "r", stdin);
	// scanf("%s", s); n=strlen(s);
	// fclose(stdin);
	// freopen("1.in", "w", stdout);

	// tr['r']['r']='r';
	// tr['g']['g']='g';
	// tr['b']['b']='b';
	// tr['r']['g']=tr['g']['r']='b';
	// tr['r']['b']=tr['b']['r']='g';
	// tr['g']['b']=tr['b']['g']='r';
	// if (m<=1e5 && 1ll*n*m<=1e10) force::solve();
	// else task1::solve();
	task::solve();
	
	return 0;
}
posted @ 2022-03-07 18:58  Administrator-09  阅读(2)  评论(0编辑  收藏  举报