题解 未来
先设法构造一个 \(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;
}