HDU-6088 Rikka with Rock-paper-scissors (容斥+MTT)
HDU-6088(容斥+MTT)
考虑计算两个人赢得次数(设为\(a,b\))都是\(d\)的倍数的方案数
注意一下\(a+b>0\)
对于\(a,b\),它的方案数为\(C(n,a)C(n-a,b)\),即\(\frac{n!}{a!b!(n-a-b)!}\)
多以对于每个\(d\)计算一遍所有可行的\(a,b\)能组成的总方案数
这个可以\(MTT\)(因为模数不确定)
\(MTT\)的实现,,在文章下面的扩展介绍里
由于是\(d\)的倍数会包含所有\(d|gcd(a,b)\)的情况,所以还需要容斥一下
复杂度\(n\ln n \log n\),以及极其大的常数
#include
using namespace std;
#define double long double
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
template inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template inline void cmax(T &a,T b){ ((a>=1,x=x*x%P) if(k&1) res=res*x%P;
return res;
}
ll qmul(ll x,ll y,ll P){
y=(y%P+P)%P;
ll res=0;
for(;y;y>>=1,x+=x,(x>=P&&(x-=P))) if(y&1) res+=x,(res>=P&&(res-=P));
return res;
}
int rev[N];
struct Cp{
double x,y;
Cp operator + (const Cp t) const { return (Cp){x+t.x,y+t.y}; }
Cp operator - (const Cp t) const { return (Cp){x-t.x,y-t.y}; }
Cp operator * (const Cp t) const { return (Cp){x*t.x-y*t.y,x*t.y+y*t.x}; }
}A[N],B[N],w[N];
void FFT(int n,Cp *a,int f){
rep(i,0,n-1) if(rev[i]>1]>>1)|((i&1)<