题意:两个人van石头剪子布的游戏一共n盘,假设A赢了a盘,B赢了b盘,那么得分是gcd(a,b),求得分的期望*\(3^{2*n}\)

题解:根据题意很明显有\(ans=3^{n}*\sum_{a=0}^{n}\sum_{b=0}^{n-a}gcd(a,b)C(n,a)C(n-a,b)\)

\(ans=\sum_{d=1}^nd\sum_{a=0}^n\sum_{b=0}^{n-a}[gcd(a,b)==d]C(n,a)C(n-a,b)\)

假设\(f(d)=\sum_{a=0}^n\sum_{b=0}^{n-a}[gcd(a,b)==d]C(n,a)C(n-a,b)\),\(F(d)=\sum_{a=0}^n\sum_{b=0}^{n-a}[d|gcd(a,b)]C(n,a)C(n-a,b)\),

那么\(F(d)=\sum_{d|x}f(x)\),\(f(d)=\sum_{d|x}\mu(\frac{x}{d})F(x)\).

\(ans=3^{n}\sum_{d=1}^nd\sum_{d|x}\mu(\frac{x}{d})F(x)\)

\(ans=3^{n}\sum_{x=1}^nF(x)\sum_{d|x}d\mu(\frac{x}{d})\)

\(ans=3^{n}\sum_{x=1}^nF(x)\phi(x)\)

\(F(d)=\sum_{a=0}^n\sum_{b=0}^{n-a}[d|gcd(a,b)]C(n,a)C(n-a,b)\)

\(F(d)=\sum_{a=0}^{\frac{n}{d}}\sum_{b=0}^{\frac{n}{d}-a}C(n,a*d)C(n-a*d,b*d)-1\)

\(F(d)=\sum_{a=0}^{\frac{n}{d}}\sum_{b=0}^{\frac{n}{d}-a}C(n,a*d+b*d)*C(a*d+b*d,b*d)-1\)

\(F(d)=\sum_{a=0}^{\frac{n}{d}}\sum_{b=0}^{a}C(n,a*d)C(a*d,b*d)-1\)

\(F(d)=n!\sum_{a=0}^{\frac{n}{d}}\frac{1}{(n-a*d)!}\sum_{b=0}^{i}\frac{1}{(j*d)!}*\frac{1}{(i*d-j*d)!}\)

后面的求和用拆系数fft即可处理,枚举d计算F(d),复杂度\(\sum_{d=1}^n\frac{n}{d}log(\frac{n}{d})\)

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
//#include <bits/extc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define mt make_tuple
//#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
#define bpc __builtin_popcount
#define base 1000000000000000000ll
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
#define mr mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;} using namespace std;
//using namespace __gnu_pbds; const ld pi=acos(-1);
const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=2000000+10,inf=0x3f3f3f3f; struct cd{
ld x,y;
cd(ld _x=0.0,ld _y=0.0):x(_x),y(_y){}
cd operator +(const cd &b)const{
return cd(x+b.x,y+b.y);
}
cd operator -(const cd &b)const{
return cd(x-b.x,y-b.y);
}
cd operator *(const cd &b)const{
return cd(x*b.x - y*b.y,x*b.y + y*b.x);
}
cd operator /(const db &b)const{
return cd(x/b,y/b);
}
}a[N*3],b[N*3],dfta[N*3],dftb[N*3],dftc[N*3],dftd[N*3];
cd conj(cd a){return cd(a.x,-a.y);}
int rev[N*3],A[N],B[N],C[N*3];
void getrev(int bit)
{
for(int i=0;i<(1<<bit);i++)
rev[i]=(rev[i>>1]>>1) | ((i&1)<<(bit-1));
}
void fft(cd *a,int n,int dft)
{
for(int i=0;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int step=1;step<n;step<<=1)
{
cd wn(cos(dft*pi/step),sin(dft*pi/step));
for(int j=0;j<n;j+=step<<1)
{
cd wnk(1,0);
for(int k=j;k<j+step;k++)
{
cd x=a[k];
cd y=wnk*a[k+step];
a[k]=x+y;a[k+step]=x-y;
wnk=wnk*wn;
}
}
}
if(dft==-1)for(int i=0;i<n;i++)a[i]=a[i]/n;
}
void mtt(int n,int m,int p) {
if(n<100&&m<100||min(n,m)<=5)
{
for(int i=0;i<=n+m;i++)C[i]=0;
for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)
{
C[i+j]+=1ll*A[i]*B[j]%p;
if(C[i+j]>=p)C[i+j]-=p;
}
return ;
}
int sz=0;
while((1<<sz)<=n+m)sz++;getrev(sz);
int len=1<<sz;
for(int i=0;i<len;i++)
{
int x=(i>n?0:A[i]%p),y=(i>m?0:B[i]%p);
a[i]=cd(x&0x7fff,x>>15);
b[i]=cd(y&0x7fff,y>>15);
}
fft(a,len,1);fft(b,len,1);
for(int i=0;i<len;i++)
{
int j=(len-i)&(len-1);
cd aa,bb,cc,dd;
aa = (a[i] + conj(a[j])) * cd(0.5, 0);
bb = (a[i] - conj(a[j])) * cd(0, -0.5);
cc = (b[i] + conj(b[j])) * cd(0.5, 0);
dd = (b[i] - conj(b[j])) * cd(0, -0.5);
dfta[j] = aa * cc;dftb[j] = aa * dd;
dftc[j] = bb * cc;dftd[j] = bb * dd;
}
for(int i=0;i<len;i++)
{
a[i] = dfta[i] + dftb[i] * cd(0, 1);
b[i] = dftc[i] + dftd[i] * cd(0, 1);
}
fft(a,len,1);fft(b,len,1);
for(int i=0;i<len;i++)
{
int da = (ll)(a[i].x / len + 0.5) % p;
int bb = (ll)(a[i].y / len + 0.5) % p;
int dc = (ll)(b[i].x / len + 0.5) % p;
int dd = (ll)(b[i].y / len + 0.5) % p;
C[i] = (da + ((ll)(bb + dc) << 15) + ((ll)dd << 30)) % p;
C[i] = (C[i]+p)%p;
}
}
int prime[N],cnt,phi[N];
bool mark[N];
void init()
{
phi[1]=1;
for(int i=2;i<N;i++)
{
if(!mark[i])prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*prime[j]<N;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
int n,p,fac,po;
int f(int d)
{
int ans=0;
for(int i=0;i<=n/d;i++)A[i]=prime[i*d],B[i]=prime[i*d];
mtt(n/d,n/d,p);
// for(int i=0;i<=n/d;i++)printf("%d ",C[i]);puts("");
for(int i=0;i<=n/d;i++)
{
ans+=1ll*prime[n-i*d]*C[i]%p;
if(ans>=p)ans-=p;
}
ans=(1ll*ans*fac-1+p)%p;
return ans;
}
int main()
{
// fin;
init();
int t;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&p);
prime[0]=prime[1]=fac=po=1;
for(int i=2;i<=n;i++)prime[i]=1ll*(p-p/i)*prime[p%i]%p;
for(int i=1;i<=n;i++)prime[i]=1ll*prime[i-1]*prime[i]%p,fac=1ll*fac*i%p,po=1ll*po*3%p;
int ans=0;
for(int d=1;d<=n;d++)
{
ans+=1ll*phi[d]*f(d)%p;
if(ans>=p)ans-=p;
}
printf("%d\n",1ll*ans*po%p);
}
return 0;
}
/******************** ********************/

最新文章

  1. Strus2第一次课:dom4j解析xml文档
  2. CGFloat Float 互转
  3. PlantUML的实例参考
  4. 【8-15】Markdown语法学习
  5. svn状态图标大全
  6. 简单的ajax封装
  7. Python 条件判断 循环
  8. Java加解密与数字签名
  9. oracle 字符集转换:AL32UTF8-&gt;ZHS16GBK
  10. 7.3.2 Using Backups for Recovery 使用备份用于恢复
  11. 总结QueueUserWorkItem传参的几种方式
  12. unity 打包 windows 运行 紫色 粉红色
  13. SICP 习题 (1.13) 解题总结
  14. ZendStudio-12.5.0-win32.win32.x86_64.msi官方版本及破解工具
  15. Storm 常用命令
  16. 【JavaScript】 使用extend继承对象的prototype方法
  17. synchronized 和lock的区别
  18. LINQ to SQL 实现 GROUP BY、聚合、ORDER BY
  19. libnids使用 (转)
  20. HTML5 通过 FileReader 实现文件上传

热门文章

  1. JDK简介和mac下安装和查看版本命令
  2. Scala 可变长参数
  3. Harry and magic string HDU - 5157 记录不相交的回文串对数
  4. 1.springboot+ActiveMQ
  5. 常用指令linux总结
  6. Mysql优化-索引
  7. JavaScript - window对象相关
  8. colormap 参数及对应色卡
  9. python3和python2编码拾遗
  10. Hibernate与数据库交互方式和Hibernate常用的几个方法