[COCI2013]DLAKAVAC

[COCI2013]DLAKAVAC

题目大意:

有一个长度为\(m(m\le1500)\)\(01\)\(A\),进行\(k(k\le10^{18})\)次操作。一次操作完的串中若\(A_i=1\),当且仅当在原串中存在\(jk\%m=i\),且\(A_j=A_k=1\)。求所有操作完成后哪些位置为\(1\)

思路:

快速幂。时间复杂度\(\mathcal O(m^2\log k)\)

源代码:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
typedef long long int64;
inline int64 getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int64 x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=1500;
int64 k;
int m,n;
bool a[N],ans[N],tmp[N];
inline void mul(bool a[],bool b[]) {
	memset(tmp,0,sizeof tmp);
	for(register int i=0;i<m;i++) {
		for(register int j=0;j<m;j++) {
			tmp[(i*j)%m]|=a[i]&&b[j];
		}
	}
	std::copy(&tmp[0],&tmp[m],a);
}
int main() {
	k=getint(),m=getint(),n=getint();
	for(register int i=0;i<n;i++) {
		a[getint()]=true;
	}
	ans[1]=1;
	for(;k;k>>=1) {
		if(k&1) mul(ans,a);
		mul(a,a);
	}
	for(register int i=0;i<m;i++) {
		if(ans[i]) printf("%d ",i);
	}
	puts("");
	return 0;
}
posted @ 2018-11-09 11:21  skylee03  阅读(244)  评论(0编辑  收藏  举报