bookshelf HDU - 6363(数论结论+莫比乌斯反演)

bookshelf HDU - 6363

Patrick Star bought a bookshelf, he named it ZYG !!

Patrick Star has N book .

The ZYG has K layers (count from 1 to K) and there is no limit on the capacity of each layer !

Now Patrick want to put all N books on ZYG :

  1. Assume that the i-th layer has cnti(0≤cnti≤N) books finally.

  2. Assume that f[i] is the i-th fibonacci number (f[0]=0,f[1]=1,f[2]=1,f[i]=f[i−2]+f[i−1]).

  3. Define the stable value of i-th layers stablei=f[cnti].

  4. Define the beauty value of i-th layers beautyi=2stablei−1.

  5. Define the whole beauty value of ZYG score=gcd(beauty1,beauty2,…,beautyk)(Note: gcd(0,x)=x).

Patrick Star wants to know the expected value of score
if Patrick choose a distribute method randomly !
Input
The first line contain a integer T (no morn than 10), the following is T test case, for each test case :

Each line contains contains three integer n,k (0<n,k106) ( 0 < n , k ≤ 106 )
.
Output
For each test case, output the answer as a value of a rational number modulo 109+7.

Formally, it is guaranteed that under given constraints the probability is always a rational number pq (p and q are integer and coprime, q is positive), such that q is not divisible by 109+7. Output such integer a between 0 and 109+6 that p−aq is divisible by 109+7
.
Sample Input

1
6 8

Sample Output

797202805
题意:

把N本书放到K层的书架上,每一层的美丽值为 bi=2f[cnt]1 b i = 2 f [ c n t ] − 1 ,其中cnt是这一层书的数量,f[x]为斐波那契数列,整个书架的美丽值为 gcd(b1,b2,...,bk) g c d ( b 1 , b 2 , . . . , b k ) ,问整个书架的美丽值的期望

分析:

首先需要利用数论中的两个结论进行化简

gcd(xa1,xb1)=xgcd(a,b)1 g c d ( x a − 1 , x b − 1 ) = x g c d ( a , b ) − 1

gcd(f[x],f[y])=f[gcd(x,y)] g c d ( f [ x ] , f [ y ] ) = f [ g c d ( x , y ) ] ( f[] f [ ] 是斐波那契数列)

于是可以进一步化简公式为 2f[gcd(cnt1,cnt2,...,cntk)]1 2 f [ g c d ( c n t 1 , c n t 2 , . . . , c n t k ) ] − 1

这样只需要枚举gcd,计算gcd出现次数就可以知道gcd的贡献值了

f(g)gcd(x1,x2,...xk)=g f ( g ) 表 示 g c d ( x 1 , x 2 , . . . x k ) = g 的 个 数

F(p)gcd(x1,x2,...xk)=gp F ( p ) 表 示 g c d ( x 1 , x 2 , . . . x k ) = g 的 倍 数 p 的 个 数

我们发现对于 f(g) f ( g ) 来说不是很好求,但是 F(p) F ( p ) 好求

如果想知道n内有多少个g的倍数的话那么应该共有 np n p 个

那么将这些数分成k份的话,利用隔板法

|||...||| | ∗ | ∗ | . . . | ∗ ∗ | ∗ ∗ |

k+1 k + 1 个板子可以得到k个盒子,中间盒子中任意放 np n p 个

那么相当于中间 np+k1 n p + k − 1 个位置的组合,其中选取k-1个位置,那么其他位置便确定了

因此 F(p)=Ck1np+k1 F ( p ) = C n p + k − 1 k − 1

而gcd的贡献值应该为 f(gcd)×(2f[gcd]1) f ( g c d ) × ( 2 f [ g c d ] − 1 )

这样我们知道了 F() F ( ) 就可以通过莫比乌斯反演计算 f() f ( )

因此可以先在 ngcdn|gcdgcdgcdp(p|n) n 的 范 围 内 枚 举 g c d ( n | g c d ) , 然 后 在 从 g c d 为 基 础 枚 举 g c d 的 倍 数 p ( p | n )

f(gcd)=gcd|pμ(pgcd)F(p)=gcd|pμ(pgcd)Ck1np+k1 f ( g c d ) = ∑ g c d | p μ ( p g c d ) F ( p ) = ∑ g c d | p μ ( p g c d ) C n p + k − 1 k − 1

这样求出 f() f ( ) 后可以乘上值 (2f[gcd]1) ( 2 f [ g c d ] − 1 )

所以答案为

ans=gcd|n2f[gcd]1gcd|pμ(pgcd)Ck1np+k1 a n s = ∑ g c d | n 2 f [ g c d ] − 1 ∑ g c d | p μ ( p g c d ) C n p + k − 1 k − 1

因为要求期望,所以再除去总的可能数

ans=ansCk1n+k1 a n s = a n s C n + k − 1 k − 1

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 5;
const LL mod = 1e9 + 7;
const LL mm = 1e9 + 6;

LL inv[maxn * 2 + 5],fac[maxn * 2 + 5];
bool check[maxn];
LL prime[maxn],mu[maxn],f[maxn],n,k;

LL exgcd(LL a,LL b,LL& x,LL& y){
    if(a == 0 && b == 0) return -1;
    if(b == 0){
        x = 1,y = 0;
        return a;
    }
    LL d = exgcd(b,a % b,y,x);
    y -= a / b * x;
    return d;
}
LL rev(LL a,LL n){
    LL x,y;
    LL d = exgcd(a,n,x,y);
    return (x % n + n) % n;
}
void init_inv(){
    fac[0] = 1;
    for(LL i = 1;i < 2 * maxn;++i) fac[i] = fac[i - 1] * i % mod;
    inv[2 * maxn - 1] = rev(fac[2 * maxn - 1],mod);
    for(LL i = 2 * maxn - 2;i >= 0;--i){
        inv[i] = (i + 1) * inv[i + 1] % mod;
    }
}
LL C(LL a,LL b){
    LL m = a,n = b;
    return ((fac[n] * inv[m]) % mod * inv[n - m]) % mod;
}
void init(){
    f[0] = 0,f[1] = 1;
    for(int i = 2;i < maxn;++i){
        f[i] = (f[i - 1] + f[i - 2]) % mm;
    }
}
void mobius(){
    memset(check,false,sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for(LL 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 a,LL n){
    LL ret = 1;
    while(n){
        if(n & 1) ret = ret * a % mod;
        a = a * a % mod;
        n = n>>1;
    }
    return ret;
}

int main(){
    init_inv();
    mobius();
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&k);
        LL denominator = C(k-1,n + k - 1);
        denominator = rev(denominator,mod);
        LL ans = 0;
        for(int i = 1;i <= n;++i){
            if(n % i) continue;
            LL div = i;
            LL contri = (qmod(2,f[div]) - 1 + mod) % mod;
            LL cnt = 0;
            for(LL j = div;j <= n;j += div){
                if(n % j) continue;
                LL d = j;
                cnt += mu[d / i] * C(k-1,n / d + k - 1) % mod;
                cnt = (cnt % mod + mod) % mod;
            }
            ans += contri * cnt % mod;
            ans %= mod;
        }
        ans = ans * denominator % mod;
        printf("%lld\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 抱歉,作为AI语言模型,我无法提供UML类图的绘制。以下是针对题目要求的对象模型描述: 类: - 出版物(Publication) - 书籍(Book) - 杂志(Magazine) - 小册子(Pamphlet) - 电影录像带(Video) - 音乐CD(CD) - 报纸(Newspaper) - 出版商(Publisher) - 读者(Reader) - 借阅记录(BorrowRecord) - 书架(Bookshelf) - 目录(Catalog) 属性: - 出版物:出版物名、出版者、获得日期、目录编号、书架位置、借出状态、借出限制 - 书籍、杂志、小册子、电影录像带、音乐CD、报纸:各自特有的属性(例如书籍可以有作者、出版日期、ISBN等) - 出版商:出版商名、联系信息等 - 读者:读者名、联系信息等 - 借阅记录:借阅日期、归还日期、借阅的出版物等 - 书架:书架编号、可容纳的出版物类型、摆放位置等 - 目录:目录编号、包含的出版物等 方法: - 出版物:借出、收回等 - 读者:借阅出版物、归还出版物等 - 书架:获取可借用的出版物列表、添加出版物等 - 目录:获取某个出版物类型的列表、添加出版物等 ### 回答2: 对于上述的图书馆馆藏出版物的对象模型,可以设计如下类图: 类Book: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 类Magazine: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 类Pamphlet: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 类FilmTape: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 类MusicCD: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 类Newspaper: - 属性: - 出版物名:String - 出版者:String - 获得日期:Date - 目录编号:String - 书架位置:String - 借出状态:boolean - 借出限制:int - 方法: - 借出:void - 收回:void 注意:上述类的属性和方法可以根据具体需求进行调整,这里仅提供一种基本的设计思路。使用UML工具进行绘制类图时,可按照上述类及其属性和方法在类图中进行呈现。 ### 回答3: 在UML工具中绘制类图如下: +-----------------------+ | LibraryCollection | +-----------------------+ | - collectionItems: List<CollectionItem> | +-----------------------+ | + addItem(item: CollectionItem): void | | + removeItem(item: CollectionItem): void | +-----------------------+ +-----------------------+ | CollectionItem | +-----------------------+ | - publicationName: String | | - publisher: String | | - acquisitionDate: Date | | - catalogNumber: String | | - shelfLocation: String | | - isBorrowed: boolean | | - borrowLimit: int | +-----------------------+ | + borrowItem(): void | | + returnItem(): void | +-----------------------+ +-----------------------+ | Book | +-----------------------+ | - isbn: String | +-----------------------+ +-----------------------+ | Magazine | +-----------------------+ | - issueNumber: int | +-----------------------+ +-----------------------+ | DVD | +-----------------------+ | - length: int | +-----------------------+ +-----------------------+ | CD | +-----------------------+ | - length: int | +-----------------------+ +-----------------------+ | Newspaper | +-----------------------+ | - publisher: String | +-----------------------+ 在这个模型中,LibraryCollection类代表图书馆的馆藏物品列表。其中包含了一个集合属性collectionItems,用于存储所有图书馆藏物品的实例。addItem()方法用于向集合中添加新的图书馆藏物品,removeItem()方法用于从集合中删除某个图书馆藏物品。 CollectionItem类代表图书馆馆藏物品的基类,包含了出版物名、出版者、获得日期、目录编号、书架位置、借出状态和借出限制等属性。borrowItem()方法用于将物品标记为已借出,returnItem()方法用于将物品标记为已归还。 Book类、Magazine类、DVD类、CD类和Newspaper类分别继承自CollectionItem类,代表了不同种类的图书馆馆藏物品。其中Book类包含了isbn属性,Magazine类包含了issueNumber属性,DVD类和CD类包含了length属性,Newspaper类包含了publisher属性。 这样的对象模型可以帮助图书馆管理其馆藏物品,对读者进行借阅和归还服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值