题目:把N本书放到K层的书架上,每一层的美丽值为bi=2*fib[cnt]−1,其中cnt是这一层书的数量,fib[ ]为斐波那契数列,整个书架的美丽值为gcd(b1,b2,...,bk),问整个书架的美丽值的期望。
看了某大佬博客上详细的分析才补上的这个题,写的太好了。
#include
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int MAXN = 1000000;
bool check[MAXN+10];
int prime[MAXN+10],mu[MAXN+10];
void Mobius()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
}
ll qmod(ll x,ll p)
{
ll ans=1;
while(p)
{
if(p&1) ans=ans*x%mod;
x=x*x%mod;
p>>=1;
}
return ans;
}
ll fac[MAXN*2+10],inv[MAXN*2+10],fib[MAXN*2+10];
void init()
{
fac[0]=1;
int N=MAXN*2;
for(int i=1;i<=N;i++)
fac[i]=fac[i-1]*i%mod;
inv[N]=qmod(fac[N],mod-2);
for(int i=N-1;i>=0;i--)
inv[i]=1ll*(i+1)*inv[i+1]%mod;
fib[0]=0,fib[1]=1;
for(int i=2;i<=N;i++)
fib[i]=(fib[i-1]+fib[i-2])%(mod-1);///fib增长速度超级快,需要利用费马小定理降幂
}
ll C(ll n,ll m)
{
if(m>n) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int t,n,k;
int main()
{
init();
Mobius();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
ll ans=0;
for(int i=1;i<=n;i++)
if(n%i==0)
{
ll tmp=0;
for(int j=i;j<=n;j+=i)
if(n%j==0)
tmp=(tmp+mu[j/i]*C(n/j+k-1,k-1)+mod)%mod;
ans+=tmp*(qmod(2,fib[i])-1)%mod;
if(ans>mod)
ans-=mod;
}
ans=ans*qmod(C(n+k-1,k-1),mod-2)%mod;
printf("%I64d\n",ans);
}
return 0;
}
下面是普通的容斥代码
#include
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int MAXN = 1000000;
ll qmod(ll x,ll p)
{
ll ans=1;
while(p)
{
if(p&1) ans=ans*x%mod;
x=x*x%mod;
p>>=1;
}
return ans;
}
ll fac[MAXN*2+10],inv[MAXN*2+10],fib[MAXN*2+10];
void init()
{
fac[0]=1;
int N=MAXN*2;
for(int i=1;i<=N;i++)
fac[i]=fac[i-1]*i%mod;
inv[N]=qmod(fac[N],mod-2);
for(int i=N-1;i>=0;i--)
inv[i]=1ll*(i+1)*inv[i+1]%mod;
fib[0]=0,fib[1]=1;
for(int i=2;i<=N;i++)
fib[i]=(fib[i-1]+fib[i-2])%(mod-1);
}
ll C(int n,int m)
{
if(m>n) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int t,n,k,p[MAXN+10];
ll ans[MAXN+10];
int main()
{
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
p[0]=0;
for(int i=1;i<=n;i++)
if(n%i==0)
p[++p[0]]=i;
for(int i=1;i<=p[0];i++)
ans[i]=C(n/p[i]+k-1,k-1)%mod;
for(int i=p[0];i>0;i--)
for(int j=i+1;j<=p[0];j++)
if(p[j]%p[i]==0)
ans[i]=(ans[i]-ans[j]+mod)%mod;
ll res=0;
for(int i=1;i<=p[0];i++)
(res+=ans[i]*(qmod(2,fib[p[i]])-1)%mod)%=mod;
res=res*qmod(C(n+k-1,k-1),mod-2)%mod;
printf("%I64d\n",res);
}
return 0;
}