[atARC134E]Modulo Nim
显然不关心于其中的0和重复数字,因此状态可以被描述为正整数集合$S$
结论:先手必败的必要条件为$S=\{1\},\{2\},\{4,8\}$或$\forall x\in S,12\mid x$
特判$\max S\le 2$的情况,显然仅有$S=\{1\}$或$\{2\}$时先手必败
考虑操作$m=2$,操作后若$S=\{1\}$则先手(原来的后手)必败,进而即$\forall x\in S,2\mid x$
考虑操作$m=4$(注意$3\not\in S$,因此$\max S\ge 4$),操作后若$S=\{2\}$则先手必败,结合之前的分析即$\forall x\in S,4\mid x$
考虑操作$m=3$,操作后若$S=\{1\}$或$\{2\}$则先手必败,进而即$\forall x\in S,3\mid x$或$\exists x,y\in S,x\equiv 1$且$y\equiv 2(mod\ 3)$
前者结合之前的分析即得到$\forall x\in S,12\mid x$,后者再分类讨论:
1.若$\max S<12$,显然$S=\{4,8\}$,那么先手必败
2.若$\max S\ge 12$,考虑操作$m=12$,操作后显然$S=\{4,8\}$,那么先手(原来的后手)必败
综上,即得证
特判几种特殊情况后,注意到$S$仅有$2^{\lfloor\frac{A}{12}\rfloor}$种(其中$A=\max a_{i}$),暴力dp判定即可
统计答案时,注意到求$S\subseteq T$的$S$数量是容易的,因此容斥即可
时间复杂度为$o((A+n)2^{\lfloor\frac{A}{12}\rfloor})$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 205 4 #define M 16 5 #define C 12 6 #define mod 998244353 7 #define ll long long 8 int n,sum,ans,a[N],v[N],f[1<<M]; 9 void set_v(int a=0,int b=0){ 10 memset(v,0,sizeof(v)); 11 if (a)v[a]=1; 12 if (b)v[b]=1; 13 } 14 int get_v(){ 15 if ((v[0]==1)&&(v[1]<3))return 1; 16 if ((v[0]==2)&&(v[1]==4)&&(v[2]==8))return 1; 17 int S=0; 18 for(int i=1;i<=v[0];i++){ 19 if (v[i]%C)return 0; 20 S|=(1<<v[i]/C-1); 21 } 22 return f[S]; 23 } 24 int cnt_v(){ 25 int ans=1; 26 for(int i=1;i<N;i++)v[i]+=v[i-1]; 27 for(int i=1;i<=n;i++)ans=(ll)ans*v[a[i]]%mod; 28 return ans; 29 } 30 int main(){ 31 for(int i=1;i<(1<<M);i++){ 32 int mx=0; 33 for(int k=0;k<M;k++) 34 if ((i>>k)&1)mx=(k+1)*C; 35 for(int j=1;j<=mx;j++){ 36 v[0]=0; 37 for(int k=0;k<M;k++) 38 if (((i>>k)&1)&&((k+1)*C%j))v[++v[0]]=(k+1)*C%j; 39 sort(v+1,v+v[0]+1); 40 v[0]=unique(v+1,v+v[0]+1)-v-1; 41 f[i]|=get_v(); 42 } 43 f[i]^=1; 44 } 45 for(int k=0;k<M;k++) 46 for(int i=0;i<(1<<M);i++) 47 if ((i>>k)&1)f[i^(1<<k)]=(f[i^(1<<k)]-f[i]+mod)%mod; 48 scanf("%d",&n),sum=1; 49 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 50 for(int i=1;i<=n;i++)sum=(ll)sum*a[i]%mod; 51 set_v(1),ans=(ans+cnt_v())%mod; 52 set_v(2),ans=(ans+cnt_v())%mod; 53 set_v(4),ans=(ans-cnt_v()+mod)%mod; 54 set_v(8),ans=(ans-cnt_v()+mod)%mod; 55 set_v(4,8),ans=(ans+cnt_v())%mod; 56 for(int i=0;i<(1<<M);i++){ 57 memset(v,0,sizeof(v)); 58 for(int k=0;k<M;k++) 59 if ((i>>k)&1)v[(k+1)*C]=1; 60 ans=(ans+(ll)f[i]*cnt_v())%mod; 61 } 62 ans=(sum-ans+mod)%mod; 63 printf("%d\n",ans); 64 return 0; 65 }