Description
将 本书等概率随机放在 层书架上,如果第 层书架上有 本书,那么该层书架的稳定值为 ,其中 为斐波那契数列,美观度为 ,此时得分为 ,求得分期望值
Input
第一行一整数 表示用例组数,每组用例输入两个整数
Output
输出得分期望值,结果模
Sample Input
1
6 8
Sample Output
797202805
Solution
首先证明两个结论:
假设
,则有
$$
\begin{array}{rcl}
gcd(2^a-1,2^b-1)&=&gcd(2^{a-b}(2^b-1)+2^{a-b}-1,2^b-1)\
&=&gcd(2^{a-b}-1,2^b-1)\
&…&\
&=&gcd(2^{a\%b}-1,2^b-1)
\end{array}
$$
辗转相除即得结论.
首先注意到
假设 ,那么有
则有
辗转相除即得结论.
现在考虑原问题,由上面两个结论即得到当 个书架上书的数量为 时,其得分即为 ,总方案数即为将 本书放入 个书架,方案数 ,假设 的方案数有 种,那么答案即为 ,故只要求出 即可
令 的方案数为 ,由插板法知
而 ,由莫比乌斯反演有 ,预处理莫比乌斯函数后直接求解即可
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 1000005
typedef long long ll;
int prime[maxn],mu[maxn],check[maxn],tot;
void Moblus(int n=1e6)
{
memset(check,0,sizeof(check));
mu[1]=1;
tot=0;
for(int i=2;i<=n;i++)
{
if(!check[i])
{
prime[tot++]=i;
mu[i]=-1;
}
for(int j=0;j<tot&&i*prime[j]<=n;j++)
{
check[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
#define mod 1000000007
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int Pow(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
int a[maxn],fact[2*maxn],inv[2*maxn];
void init(int n=1e6)
{
Moblus();
a[0]=0,a[1]=1;
for(int i=2;i<=1e6;i++)a[i]=(a[i-2]+a[i-1])%(mod-1);
for(int i=1;i<=1e6;i++)a[i]=add(Pow(2,a[i]),mod-1);
fact[0]=1;
for(int i=1;i<=2*n;i++)fact[i]=mul(i,fact[i-1]);
inv[1]=1;
for(int i=2;i<=2*n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
inv[0]=1;
for(int i=1;i<=2*n;i++)inv[i]=mul(inv[i],inv[i-1]);
}
int C(int n,int m)
{
if(m<0||m>n)return 0;
return mul(fact[n],mul(inv[m],inv[n-m]));
}
int F(int d,int k)
{
return C(d+k-1,k-1);
}
int main()
{
init();
int T,n,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
int ans=0;
for(int d=1;d<=n;d++)
if(n%d==0)
{
int f=0;
for(int i=d;i<=n;i+=d)
if(n%i==0)
{
if(mu[i/d]==1)f=add(f,F(n/i,k));
else if(mu[i/d]==-1)f=add(f,mod-F(n/i,k));
}
ans=add(ans,mul(f,a[d]));
}
printf("%d\n",mul(ans,Pow(C(n+k-1,k-1),mod-2)));
}
return 0;
}