[COCI2013]DLAKAVAC
题目大意:
有一个长度为(m(mle1500))的(01)串(A),进行(k(kle10^{18}))次操作。一次操作完的串中若(A_i=1),当且仅当在原串中存在(jk\%m=i),且(A_j=A_k=1)。求所有操作完成后哪些位置为(1)。
思路:
快速幂。时间复杂度(mathcal O(m^2log 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;
}