题解 细菌培养

传送门

(不太记得了,复述题解中)
先原根转化,那么可以变成加法
发现把所有的 0 当成 1 去计算,之后再用 0 覆盖受影响的区域,不会影响答案的正确性
那么令 \(b\) 为原根转化后序列的集合幂级数
相当于每次乘 \(1+x+x^{-1}\pmod {x^n}\)
然后发现 \((1+x+x^{-1})^{2^t}\pmod {4}\) 只有 \(O(1)\) 项是有值的
证明可以组合数算转移路径,然后 Lucas 定理
那么可以将 t 四进制拆分,进行 log 次单项式乘多项式
这样复杂度就是 \(O(n\log n)\)

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

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
	ll ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
ll t;
int a[N];
const ull base=13131;
const int mod=5, inv2=(mod+1)>>1, phi=mod-1, rt=2;
inline int qpow(int a, ll b, ll mod=::mod) {int ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}

namespace force{
	int f[2][N], now;
	void solve() {
		for (int i=0; i<n; ++i) f[now][i]=a[i];
		for (int i=1; i<=t; ++i,now^=1) {
			for (int j=0; j<n; ++j) f[now^1][j]=0;
			for (int j=0; j<n; ++j) f[now^1][j]=f[now][((j-1)%n+n)%n]*f[now][j]*f[now][(j+1)%n]%mod;
		}
		for (int j=0; j<n; ++j) printf("%d ", f[now][j]); cout<<endl;
	}
}

namespace task1{
	void solve() {
		int ans=qpow(a[0], qpow(3, t, mod-1));
		for (int i=0; i<n; ++i) printf("%d ", ans); cout<<endl;
	}
}

namespace task2{
	int f[2][N], now, loop;
	map<ull, bool> mp;
	void one() {
		for (int j=0; j<n; ++j) f[now^1][j]=0;
		for (int j=0; j<n; ++j) f[now^1][j]=f[now][((j-1)%n+n)%n]*f[now][j]*f[now][(j+1)%n]%mod;
		now^=1;
	}
	ull h() {
		ull ans=0;
		for (int i=0; i<n; ++i) ans=ans*base+f[now][i];
		return ans;
	}
	void solve() {
		for (int i=0; i<n; ++i) f[now][i]=a[i];
		mp[h()]=1;
		for (int i=1,loop; i<=t; ++i) {
			one();
			ull t=h();
			if (mp.find(t)!=mp.end()) {
				t%=(loop=i-1); ++i;
				while (i<=t) one();
				break;
			}
			else mp[t]=1;
		}
		for (int j=0; j<n; ++j) printf("%d ", f[now][j]); cout<<endl;
	}
}

namespace task3{
	int rev[N], bct, bln;
	int b[N], f[N], tem[N], id[N], mp[N], dlt[N];
	void mul(int* a, int* b) {
		for (int i=0; i<bln; ++i) tem[i]=0;
		for (int i=0; i<n; ++i)
			for (int j=0; j<n; ++j)
				tem[i+j]=(tem[i+j]+a[i]*b[j])%phi;
		for (int i=n; i<bln; ++i) tem[i%n]=(tem[i%n]+tem[i])%phi;
		for (int i=0; i<n; ++i) a[i]=tem[i];
	}
	void solve() {
		for (int i=0; i<n; ++i) if (!a[i]) {
			if (t>=n/2) {for (int j=0; j<n; ++j) printf("0%c", " \n"[j==n-1]); exit(0);}
			int left=i, right=n-1-i;
			if (t>right) ++dlt[i], --dlt[n], ++dlt[0], --dlt[t-right];
			else ++dlt[i], --dlt[i+t+1];
			if (t>left) ++dlt[0], --dlt[i+1], ++dlt[n-1-(t-left)+1], --dlt[n+1];
			else ++dlt[i-t], --dlt[i+1];
		}
		for (int i=0; i<phi; ++i) id[mp[i]=qpow(rt, i)]=i;
		for (int i=0; i<n; ++i) b[i]=id[a[i]];
		// cout<<"b: "; for (int i=0; i<n; ++i) cout<<b[i]<<' '; cout<<endl;
		for (bln=1; bln<2*n; bln<<=1,++bct);
		++f[0], ++f[1%n], ++f[n-1];
		for (int i=1; i<=t; ++i) mul(b, f);
		for (int i=1; i<n; ++i) dlt[i]+=dlt[i-1];
		for (int i=0; i<n; ++i) printf("%d%c", dlt[i]?0:mp[b[i]], " \n"[i==n-1]);
	}
}

namespace task4{
	int rev[N], bct, bln;
	int b[N], f[N], t1[N], t2[N], id[N], mp[N], dlt[N];
	inline int qpow(int a, ll b, ll mod=::mod) {int ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
	void mul(int* a, int* b) {
		for (int i=0; i<bln; ++i) t1[i]=0;
		for (int i=0; i<n; ++i)
			for (int j=0; j<n; ++j)
				t1[i+j]=(t1[i+j]+a[i]*b[j])%phi;
		for (int i=n; i<bln; ++i) t1[i%n]=(t1[i%n]+t1[i])%phi;
		for (int i=0; i<n; ++i) a[i]=t1[i];
	}
	void qpow(int* a, ll b) {
		for (int i=0; i<bln; ++i) t2[i]=a[i]; --b;
		for (; b; mul(a, a),b>>=1) if (b&1) mul(t2, a);
		for (int i=0; i<bln; ++i) a[i]=t2[i];
	}
	void solve() {
		for (int i=0; i<n; ++i) if (!a[i]) {
			if (t>=n/2) {for (int j=0; j<n; ++j) printf("0%c", " \n"[j==n-1]); exit(0);}
			int left=i, right=n-1-i;
			if (t>right) ++dlt[i], --dlt[n], ++dlt[0], --dlt[t-right];
			else ++dlt[i], --dlt[i+t+1];
			if (t>left) ++dlt[0], --dlt[i+1], ++dlt[n-1-(t-left)+1], --dlt[n+1];
			else ++dlt[i-t], --dlt[i+1];
		}
		for (int i=0; i<phi; ++i) id[mp[i]=qpow(rt, i)]=i;
		for (int i=0; i<n; ++i) b[i]=id[a[i]];
		// cout<<"b: "; for (int i=0; i<n; ++i) cout<<b[i]<<' '; cout<<endl;
		for (bln=1; bln<2*n; bln<<=1,++bct);
		++f[0], ++f[1%n], ++f[n-1];
		// cout<<"f: "; for (int i=0; i<n; ++i) cout<<f[i]<<' '; cout<<endl;
		// for (int i=1; i<=t; ++i) mul(b, f);
		if (t) qpow(f, t), mul(b, f);
		for (int i=1; i<n; ++i) dlt[i]+=dlt[i-1];
		for (int i=0; i<n; ++i) printf("%d%c", dlt[i]?0:mp[b[i]], " \n"[i==n-1]);
	}
}

namespace task{
	int sta[N], bct, bln;
	int b[N], f[N], t1[N], t2[N], id[N], mp[N], dlt[N], top;
	inline int qpow(int a, ll b, ll mod=::mod) {int ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
	void mul(int* a, int* b) {
		top=0;
		for (int i=0; i<bln; ++i) t1[i]=0;
		for (int i=0; i<n; ++i) if (a[i]) sta[++top]=i;
		for (int j=0; j<n; ++j) if (b[j])
			for (int i=1; i<=top; ++i)
				t1[sta[i]+j]=(t1[sta[i]+j]+a[sta[i]]*b[j])%phi;
		for (int i=n; i<bln; ++i) t1[i%n]=(t1[i%n]+t1[i])%phi;
		for (int i=0; i<n; ++i) a[i]=t1[i];
	}
	void qpow(int* a, ll b) {
		for (int i=0; i<bln; ++i) t2[i]=a[i]; --b;
		for (; b; mul(a, a),b>>=1) if (b&1) mul(t2, a);
		for (int i=0; i<bln; ++i) a[i]=t2[i];
	}
	void solve() {
		for (int i=0; i<n; ++i) if (!a[i]) {
			if (t>=n/2) {for (int j=0; j<n; ++j) printf("0%c", " \n"[j==n-1]); exit(0);}
			int left=i, right=n-1-i;
			if (t>right) ++dlt[i], --dlt[n], ++dlt[0], --dlt[t-right];
			else ++dlt[i], --dlt[i+t+1];
			if (t>left) ++dlt[0], --dlt[i+1], ++dlt[n-1-(t-left)+1], --dlt[n+1];
			else ++dlt[i-t], --dlt[i+1];
		}
		for (int i=0; i<phi; ++i) id[mp[i]=qpow(rt, i)]=i;
		for (int i=0; i<n; ++i) b[i]=id[a[i]];
		// cout<<"b: "; for (int i=0; i<n; ++i) cout<<b[i]<<' '; cout<<endl;
		for (bln=1; bln<2*n; bln<<=1,++bct);
		++f[0], ++f[1%n], ++f[n-1];
		for (int i=0; i<n; ++i) t2[i]=f[i];
		for (; t; mul(f, f),t>>=1) if (t&1) mul(b, f);
		// for (int i=1; i<=t; ++i) mul(b, f);
		// if (t) qpow(f, t), mul(b, f);
		for (int i=1; i<n; ++i) dlt[i]+=dlt[i-1];
		for (int i=0; i<n; ++i) printf("%d%c", dlt[i]?0:mp[b[i]], " \n"[i==n-1]);
	}
}

signed main()
{
	freopen("bacteria.in", "r", stdin);
	freopen("bacteria.out", "w", stdout);

	n=read(); t=read();
	bool all_same=1;
	for (int i=0; i<n; ++i) a[i]=read()%mod;
	for (int i=1; i<n; ++i) if (a[i]!=a[i-1]) all_same=0;
	// if (all_same) task1::solve();
	// else if (t<=2000) force::solve();
	// else task2::solve();
	// task3::solve();
	task::solve();

	return 0;
}
posted @ 2022-05-07 22:00  Administrator-09  阅读(2)  评论(0编辑  收藏  举报