「CodeChef Dec13 REALSET」 Petya and Sequence 循环卷积
题目大意:
T组询问。
每组给一个数组,询问该数组是否循环移位线性无关,输出YES或NO。
题解:
LCA冬令营有讲……然而当时……
并不知道如何计算一个数组是否循环移位线性无关……网上也没有……学校还加了白名单,翻不了墙,看不了wiki(英文看不懂……)。所以这就是我怂题解的理由23333。
题解上说wiki上循环矩阵的行列式等于其DFT后点值乘积。即对于矩阵:
有:
显然如果循环数组的矩阵的轶不为n的话其行列式必然为0。
所以把数组DFT以后看一下其乘积是否为0即可。
证明什么的……留个坑吧。
看到了一个大神打了几十行……没看懂在干什么……
LCA说还可以用分圆多项式,然而并没有找到资料。再留个坑吧……
代码:
1 #include "bits/stdc++.h" 2 3 using std::swap; 4 5 inline int read () { 6 int s=0,k=1;char ch=getchar(); 7 while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); 8 while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); 9 return s*k; 10 } 11 12 typedef long long ll; 13 14 const int N=1e5+10; 15 16 ll mod,g,w[2][N],W[2][N],n,m; 17 18 inline ll gcd (ll a,ll b) { 19 return b?gcd(b,a%b):a; 20 } 21 22 inline ll Mult ( ll a,ll b ) { 23 return ( a*b - (ll)( (long double) a*b/mod )*mod + mod )% mod; 24 } 25 26 inline ll powmod ( ll a, ll b ) { 27 ll ret=1; 28 while (b) { 29 if (b&1) ret=Mult ( ret, a ); 30 b>>=1,a=Mult ( a, a); 31 }return ret; 32 } 33 34 inline int is_prim(ll x) { 35 for (int i=2;1ll*i*i<=x;++i) 36 if (x%i==0) return false; 37 return true; 38 } 39 40 inline int is_prim_root(ll x,ll y){ 41 for (int i=1;1ll*i*i<y;++i) 42 if ((y-1)%i==0) { 43 if (powmod(x,i)==1) return false; 44 if (powmod(x,(y-1)/i)==1)return false; 45 } 46 return true; 47 } 48 49 inline void init () { 50 for (m=1;m<=2*n;m<<=1); 51 ll lcm = n*m/gcd(n,m); 52 mod = lcm + 1; 53 for (int i=30;~i;--i) 54 if (mod + (lcm<<i)<1e3*n) mod+=lcm<<i; 55 while (mod<1e3*n) mod+=lcm; 56 while (!is_prim(mod)) mod+=lcm; 57 for (g=2;;++g) { 58 int flag=true; 59 for (int i=2;1ll*i*i<=mod;++i) if ((mod-1)%i==0){ 60 if (powmod(g,i)==1) {flag=false;break;} 61 if (powmod(g,(mod-1)/i)==1) {flag=false;break;} 62 } 63 if (flag) break; 64 } 65 66 ll w0=powmod(g,(mod-1)/m); 67 w[0][0]=w[1][0]=1; 68 int i; 69 for (i=1;i<m;++i) w[0][i]=Mult(w[0][i-1],w0); 70 for (i=1;i<m;++i) w[1][i]=w[0][m-i]; 71 w0=powmod(g,(mod-1)/n); 72 W[0][0]=W[1][0]=1; 73 for (i=1;i<n;++i) W[0][i]=Mult(W[0][i-1],w0); 74 for (i=1;i<n;++i) W[1][i]=W[0][n-i]; 75 } 76 77 78 inline void NTT(ll *a,int n,int f) { 79 register int i,j,k,l,t; 80 for (i=j=0;i^n;++i) { 81 if (i>j) std::swap(a[i],a[j]); 82 for (k=n>>1;(j^=k)<k;k>>=1); 83 } 84 for (i=1;i<n;i<<=1) 85 for (j=0,t=n/(i<<1);j<n;j+=i<<1) 86 for (k=l=0;k<i;++k , l+=t ) { 87 ll x=a[j+k],y=Mult(a[i+j+k],w[f][l]); 88 a[j+k]=x+y; 89 a[i+j+k]=x-y; 90 if (a[j+k]>=mod) a[j+k]-=mod; 91 if (a[i+j+k]<0) a[i+j+k]+=mod; 92 } 93 if (f ) { 94 ll rev=powmod ( n,mod-2 ); 95 for (i=0;i<n;++i) a[i]=Mult(a[i],rev); 96 } 97 } 98 99 100 inline void Bluesteins(ll *a,int f){ 101 static ll X[N],Y[N]; 102 register int i; 103 for (i=0;i<2*n;++i) Y[2*n-1-i]=W[f][1ll*i*(i-1)/2%n]; 104 for (i=2*n;i<m;++i) Y[i]=0; 105 NTT(Y,m,0); 106 for (i=0;i<n;++i) X[i]=Mult(a[i],W[f][ (n-1ll*i*(i-1)/2%n)%n ]); 107 for (i=n;i<m;++i) X[i]=0; 108 NTT(X,m,0); 109 for (i=0;i<m;++i) X[i]=Mult(X[i],Y[i]); 110 NTT(X,m,1); 111 for (i=0;i<n;++i) 112 a[i]=Mult (X[2*n-1-i],W[f][(n-1ll*i*(i-1)/2%n)%n ]); 113 if (f) { 114 ll rev=powmod(n,mod-2); 115 for (i=0;i<n;++i) a[i]=Mult(a[i],rev); 116 } 117 } 118 119 ll a[N]; 120 121 int main (int argc, char const* argv[]){ 122 //freopen("Dec13Realset.in","r",stdin); 123 int T=read(),i; 124 while (T-- ){ 125 n=read(); 126 for (i=0;i<n;++i) a[i]=read(); 127 init(); 128 Bluesteins(a,0); 129 ll flag=1; 130 for (i=0;i<n;++i) flag=Mult(flag,a[i]); 131 puts(flag?"NO":"YES"); 132 } 133 return 0; 134 }
没有什么不可能。