- 1500ms
- 131072K
Nim is a famous game as you know. Nim is a 2-player game featuring several piles of stones. Players alternate turns, and on his/her turn, a player's move consists of removing one or more stones from any single pile. Play ends when all the stones have been removed. The first player who can't remove is declared as the loser.
Now you want to play the Great Nim Game. In the other words, you want to choose several (0 ~ N) pile(s) from N piles of stones. You want know how many choices you have making sure that the first player must win. They both try their best (optimal strategy) to win through the game.
Input
The first line contains two numbers N x1, denoting the number of piles and the number of stones in the first pile.
The second line contains five integers a, b, c, d, e
The third line contains one integer kk, denoting a function
f(x)=
(ax^4+bx^3+cx^2+dx^1+e - 1)%k+1.
With these, you can figure out the number of stones in the i-th pile xi=f(xi−1)(1<i≤N)
It is guaranteed that
1<N<1010000000,
0<x1≤k,0≤a,b,c,d,e<2^12,
a+b+c+d+e>0,0<k<2^12.
Output
Print the number of solutions making sure the first player must win. The answer may be very large, so you should output it mod 1e9+7 (% 1000000007).
Hint
In the first sample, there are 1,2,3,4,5 stones in the 1-st, 2-nd, 3th, 4th, 5th pile. You can figure out there are exactly 4 choosing ({1,2,3}{1,4,5}{2,3,4,5}{}(empty, you choose zero pile)) ways that make first-hand player must lose, so the answer is 2^5-4=2825−4=28.
If x is in range (1<=x<= k), f(x)(1≤x≤k),f(x) must be in range (1≤f(x)≤k), too.
样例输入1
5 1
0 0 0 1 1
16
样例输出1
28
样例输入2
100000000000000000000 1
0 0 0 1 1
4095
样例输出2
394326889
样例输入3
100000000000000000000 1
1 0 0 1 1
4095
样例输出3
933180537
题目来源
参考博客:https://blog.csdn.net/nudt_spy/article/details/82453579
AC的C++代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=4100;
bool flag[N];//vis[i]记录数i是否出现
int X[N];//记录X[i]的值
int dp[2][N];
ll f(ll x,ll n)
{
ll res=1;
while(n>0){
if(n&1)
res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main()
{
string s;
ll a,b,c,d,e,k,x;
while(cin>>s>>x>>a>>b>>c>>d>>e>>k){
ll t=0;
int num=0;//num记录能出现多少个不同的x
for(int i=0;i<s.length();i++){
t=(t*10+(s[i]-'0'))%(mod-1);
if(num<=4096)
num=num*10+(s[i]-'0');
}
memset(flag,false,sizeof(flag));
memset(dp,0,sizeof(dp));
X[1]=x;//X1为x
flag[x]=true;//x这个数出现了
for(int i=2;i<=num;i++){//计算这num个不同的x值
int f=X[i-1];
X[i]=(a*f*f*f*f+b*f*f*f+c*f*f+d*f+e-1)%k+1;
//如果X[i]这个数已经出现了那么后面的x都是已经出现的数了,这时就跳出
if(flag[X[i]]){
num=i-1;
break;
}
else//如果没出现就标记
flag[X[i]]=true;
}
dp[0][0]=1;
int x=0,y=1;
for(int i=1;i<=num;i++,swap(x,y))//考虑这num个不同的数
for(int j=0;j<N;j++)
dp[y][j]=(dp[x][j^X[i]]+dp[x][j])%mod;
ll ans=0;
for(int j=1;j<4096;j++)
ans=(ans+dp[x][j])%mod;
t=(t-num%(mod-1)+(mod-1))%(mod-1);
cout<<ans*f(2,t)%mod<<endl;
}
return 0;
}