题目大意
现有n个石子堆组成的nim游戏。
每个石子堆中有i个石子的概率都是p(i)的,石子堆之间互相独立。每个石子堆最多100个石子。
问先手有必胜策略的概率。n<=10^9
分治
假如我们设dp[i,j]表示i个石子堆nim和为j的概率
显然dp[1]=p
那么dp[i]=dp[i-1]Xdp[1]
X是一种特殊定义的乘法,具体是这样的
(AXB)[j]=∑127k=0A[k]∗B[j xor k]
那么dp[n]=dp[1]n
然后快速幂即可
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
const int maxm=200+10;
db dp[maxm],f[maxm],p[maxm],ans;
int i,j,k,l,t,n,m;
void solve(int n){
if (!n){
dp[0]=1;
return;
}
solve(n/2);
int i,j,k;
fo(i,0,127) f[i]=0;
fo(j,0,127)
fo(k,0,127)
f[j^k]+=dp[j]*dp[k];
fo(i,0,127) dp[i]=0;
if (n%2){
fo(j,0,127)
fo(k,0,127)
dp[j^k]+=f[j]*p[k];
}
else fo(i,0,127) dp[i]=f[i];
}
int main(){
scanf("%d%d",&n,&m);
fo(i,0,m) scanf("%lf",&p[i]);
solve(n);
fo(i,1,127) ans+=dp[i];
printf("%.8lf\n",ans);
}