hdu 6363 bookshelf (容斥+欧拉降幂)

http://acm.hdu.edu.cn/showproblem.php?pid=6363

题意:

有 N 本一摸一样的书,有一个共有K 层的书架,现在要把书都放到书架上。

放完后假设第 i层书架有 Bi本书,则该层书架的稳固值为2^{Bi}-1 。

定义整个书架的美观值为所有层书架的稳固值的 GCD 。

问现在随机放这些书,整个书架的美观值的期望值是多少。

思路:

Part 1

 

一个放 x 本书的层美观函数为 b(x)=2^{Fx}-1

整个书架的美观值为各层美观值的最大公约数,考察任意两项:

  1. gcd(b(x),b(y)) =gcd(2^{F_x}-1,2^{F_y}-1) =2^{gcd(F_x,F_y)}-1 =2^{F_{gcd(x,y)}}-1

所以,对于 n=x_1+x_2+..+x_k(x_i>=0) 的任一有序拆分方法来说:

  1. 设他们的 gcd 为 g = gcd(x_1,x_2,x_3...x_k)
  2. 书架的美观值即 = 2^{F_g}-1
  3. 所以我们枚举 g 然后只要能计算公共GCD是 g 的方案数有多少种即可。

Part 2

那么首先这个 gg 一定是 nn 的约数,所以我们直接对 nn 的约数容斥就好了。

我们可以计算约数至少为 gg 的方案数:

  1. 每一层都是 g 的倍数,所以我们只要分配系数即可。
  2. 系数的和为\frac{n}{g},共 k 个系数,每个非负,方案数是个经典组合数 C(\frac{n}{g} + k - 1, k - 1)

然后容斥下把是 g的倍数但不是 g 的那些方案数扣掉。

就得到了严格是 g的方案数,所以从大的约数往小的约数做。

Part 3

最后就只剩下一个细节:计算 2^{F_g}​​​​ 这个东西。

由于F_g非常的爆炸,所以要采用欧拉降幂。

因为他的数满足斐波那契数列,2^{F_g}可以直接预处理出来。

 

#include 
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int maxn=2e6+10;
ll inv[maxn],fac[maxn],a[maxn],f[maxn];
ll poww(ll a,ll b)
{
    ll ans=1;
    a%=mod;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
void init()
{
    f[0]=1;f[1]=2;
    fac[0]=fac[1]=1;
    inv[1]=1;
    for(int i=2;i=1;--i)
        {
            if(n%i==0)
            {
                ll m=n/i;
                a[i]=C(m+k-1,k-1)%mod;
                for(ll j=2*i;j<=n;j+=i)
                {
                    a[i]=(a[i]-a[j]+mod)%mod;
                }
                ans=ans+a[i]*(f[i]-1+mod)%mod;
                ans%=mod;
            }
        }
        ans=ans*poww(sum,mod-2)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(容斥原理)