原题 : hdu 6363
题意 :
n本书塞进k个书架,第i层的书为x,那么第i层的价值 vi v i 为 2F(x)−1(F(x)为斐波那契数列) 2 F ( x ) − 1 ( F ( x ) 为 斐 波 那 契 数 列 ) ,求 gcd(v1...vk) g c d ( v 1 . . . v k ) 的期望 (gcd(0,x)=x) ( g c d ( 0 , x ) = x )
解析 :
对于任意两个书架的书的数量a,b
对于n的任意分割情况 n=x1+x2+...+xk设:ans=gcd(v1...vk),d=gcd(x1,x2...xk) n = x 1 + x 2 + . . . + x k 设 : a n s = g c d ( v 1 . . . v k ) , d = g c d ( x 1 , x 2... x k )
那么我们可以遍历所有的可能的d,并得出d所对应的出现次数
这个做法和前几天做的欧拉函数的题差不多,对n的因数容斥一下就好
容斥: 对于一个n的因数x,d(上述)为x的倍数的方案数为 Ck+1n/x+k+1 C n / x + k + 1 k + 1 (看成n/x个x块,中间插k-1个板子分成k个部分(0也合法),方案数为全排列除去板子的顺序和块的顺序) 当然,这种方法把d=x,2x,ix都包括进来了,所以从上往下维护去重便是d=x的次数了 |
考虑到
2F(d)
2
F
(
d
)
要炸,需要用欧拉降幂处理 a和p互质的情况下,ab%p=ab%ϕ(p)%p a 和 p 互 质 的 情 况 下 , a b % p = a b % ϕ ( p ) % p a和p不互质的情况下,ab%p=ab%phi(p)+phi(p)%p a 和 p 不 互 质 的 情 况 下 , a b % p = a b % p h i ( p ) + p h i ( p ) % p |
最终答案为:
代码:
#include<bits/stdc++.h>
#define debug(ii) printf("-> %lld\n",ii)
#define mmm(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=2000000;//C(n+k-1,k-1)所以开两倍
const ll mod =1e9+7;
ll swift(ll a,ll b){
ll ans=1;
while(b){
if(b&1ll)ans=ans*a%mod;
b>>=1;a=a*a%mod;
}
return ans;
}
ll g[N+9],fac[N+9],inv_fac[N+9],f[N+9];
ll C(ll a,ll b){
if(b>a||b<0||a<0)return 0;
return fac[a]*inv_fac[b]%mod*inv_fac[a-b]%mod;
}
void init(){
fac[1]=fac[0]=1;
for(ll i=2;i<=N;i++)
fac[i]=fac[i-1]*i%mod;
inv_fac[N]=swift(fac[N],mod-2);
for(ll i=N-1;i>=0;i--)
inv_fac[i]=inv_fac[i+1]*(i+1ll)%mod;
f[0]=0,f[1]=1;
for(int i=2;i<=N;i++)
f[i]=(f[i-1]+f[i-2])%(mod-1);//欧拉降幂
}
ll vd[N+9],tot;
int main(){
init();
int t;scanf("%d",&t);
while(t--){
mmm(g,0);tot=0;
ll n,k;scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++)if(n%i==0)vd[++tot]=i;
for(int i=tot;i>0;i--){
ll d=vd[i];
g[d]=C(n/d+k-1,k-1);
for(int j=i+1;j<=tot;j++)
if(vd[j]%d==0)
g[d]=(g[d]-g[vd[j]]+mod)%mod;
}
ll ans=0;
for(int i=1;i<=tot;i++){
ll d=vd[i];
ans=(ans+(swift(2,f[d])-1)%mod*g[d]%mod)%mod;
}
ans=ans*swift(C(n+k-1,k-1),mod-2)%mod;
printf("%lld\n",ans);
}
}