CF273E Dima and Game 题解
大家都是打表做的,但是没人说怎么打表。
首先肯定是要算出 sg 值的,然后发现
剩下的随便 dp 一下就可以了。
#include<bits/stdc++.h>
// #define ONLINE_JUDGE
#define INPUT_DATA_TYPE int
#define OUTPUT_DATA_TYPE int
inline __attribute((always_inline)) INPUT_DATA_TYPE read(){register INPUT_DATA_TYPE x=0;register char f=0,c=getchar();while(c<'0'||'9'<c)f=(c=='-'),c=getchar();while('0'<=c&&c<='9')x=(x<<3)+(x<<1)+(c&15),c=getchar();return f?-x:x;}void print(OUTPUT_DATA_TYPE x){if(x<0)x=-x,putchar('-');if(x>9)print(x/10);putchar(x%10^48);return;}
const long long mod=1000000007;
int pos[1000],sg[1000];
long long cntSg[4],f[1010][4],p;
long long getSum(long long l,long long r){
l=p-l,r=p-r;
return (l+r)*(l-r+1)/2%mod;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("name.in", "r", stdin);
freopen("name.out", "w", stdout);
#endif
register int i,j,k,cnt=0,u=1,v=1,n;
register long long uMax,vMax;
n=read();p=read();
pos[++cnt]=2;
while(pos[cnt]<p){
uMax=pos[u]*3+2;
if(pos[v]&1) vMax=(pos[v]-1)/2*3+1;
else vMax=pos[v]/2*3;
for(i=0;i<2;++i)
if(sg[u]!=i&&sg[v]!=i)
break;
if(i!=sg[cnt]) sg[++cnt]=i;
pos[cnt]=std::min(uMax,vMax);
if(uMax==pos[cnt]) ++u;
if(vMax==pos[cnt]) ++v;
}
for(i=1;i<=cnt;++i)
(cntSg[sg[i]]+=getSum(pos[i-1]+1,std::min(pos[i],(int)p)))%=mod;
f[0][0]=1;
for(i=1;i<=n;++i)
for(j=0;j<4;++j)
for(k=0;k<4;++k)
(f[i][j^k]+=cntSg[j]*f[i-1][k])%=mod;
print((f[n][1]+f[n][2]+f[n][3])%mod);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}