[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 }
View Code

 

posted @ 2022-02-02 11:02  PYWBKTDA  阅读(161)  评论(0编辑  收藏  举报