Mind control

组合

一道组合数学题,做得很蛋疼,仿佛回到了高中数竞的生活(qaq), 链接
http://acm.fzu.edu.cn/problem.php?pid=2303

解析

题目的意思很简单,把m个cake分给n个person, 每个person最多能拿一个cake, 然后这些person是有继承关系的,即这个人拿到蛋糕后,你能得到的信任是这个人以及它所有的子结点的值,求你能得到的值的期望。显然,当 m ≥ n m \geq n mn时,由鸽巢原理知,最后一个peron至少能拿到一个cake,所以总的值为n,当 m < n m<n m<n时呢?显然你也知道了,决定权都会在最后一个手上,因为这个person拿了cake,那么你就能得到他的所有子结点的值。那么我们只要关注cake分到的最后一个person就好了。
所有的方案数 C n m C_{n}^{m} Cnm,对于长度 i i i, 我们指定第 i i i个person拿一个cake,剩下的cake分给 i − 1 i-1 i1个person即可,那么总的方案数为:
∑ i = m n i ⋅ C i − 1 m − 1 \sum_{i=m}^{n} i\cdot C_{i-1}^{m-1} i=mniCi1m1答案为
a n s = ∑ i = m n i ⋅ C i − 1 m − 1 C n m ans=\frac{\sum_{i=m}^{n} i\cdot C_{i-1}^{m-1}}{C_{n}^{m}} ans=Cnmi=mniCi1m1这样貌似做出来,但突然发现 n , m ≤ 1000000 n,m\leq 1000000 n,m1000000,这个数据范围,3秒也无能为力的,所以我们尝试对分子进行化简下
i ⋅ C i − 1 m − 1 = i ⋅ ( i − 1 ) ! ( m − 1 ) ! ( i − m ) ! = m ⋅ i ! m ! ( i − m ) ! = m ⋅ C i m i \cdot C_{i-1}^{m-1}=\frac{i \cdot (i-1)!}{(m-1)!(i-m)!}=\frac{m \cdot i!}{m!(i-m)!}=m\cdot C_{i}^{m} iCi1m1=(m1)!(im)!i(i1)!=m!(im)!mi!=mCim有点眉目了,但好像还是不能做的样子(qaq)。所以还是得仔细研究下,显然这个组合数的取数是固定的,而总的数是在增加的,所以尝试研究下这里面有什么关系
C n + 1 k = ( n + 1 ) ! k ! ( n + 1 − k ) ! = ( n + 1 ) ⋅ n ! ( n + 1 − k ) ⋅ k ! ( n − k ) ! = ( 1 + k n + 1 − k ) C n k C_{n+1}^{k}=\frac{(n+1)!}{k!(n+1-k)!}=\frac{(n+1)\cdot n!}{(n+1-k)\cdot k!(n-k)!}=(1+\frac{k}{n+1-k})C_{n}^{k} Cn+1k=k!(n+1k)!(n+1)!=(n+1k)k!(nk)!(n+1)n!=(1+n+1kk)Cnk然后移项下有
C n + 1 k − C n k = k n + 1 − k C n k = C n k − 1 C_{n+1}^{k}-C_{n}^{k}=\frac{k}{n+1-k}C_{n}^{k}=C_{n}^{k-1} Cn+1kCnk=n+1kkCnk=Cnk1是不是看出什么猫腻了(hahaha),我们将上述式子构造 n n n个相加
C 1 k − C 0 k = C 0 k − 1 C_{1}^{k}-C_{0}^{k}=C_{0}^{k-1} C1kC0k=C0k1 C 2 k − C 1 k = C 1 k − 1 C_{2}^{k}-C_{1}^{k}=C_{1}^{k-1} C2kC1k=C1k1 ⋮ \vdots C n + 1 k − C n k = C n k − 1 C_{n+1}^{k}-C_{n}^{k}=C_{n}^{k-1} Cn+1kCnk=Cnk1可得 C n + 1 k = ∑ i = 0 n C i k − 1 C_{n+1}^{k}=\sum_{i=0}^{n}C_{i}^{k-1} Cn+1k=i=0nCik1
那么只要预处理下阶乘答案就行了。(不知道为什么我交了还是超时,可能是输入输出太多了,所以该用Fast-IO就AC了)

AC代码

/*
 小学生一发的刷题之路;
 今天你刷题了吗???
 
*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI=acos(-1.0);
const int maxn=1e6+5;
const ll mod=1e9+7;
template<class T>
inline void read(T &ret){       //快速输入模版;
    ret=0;
    int f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        ret=ret*10+c-'0';
        c=getchar();
    }
    ret*=f;
}
template <class T>
inline void out(T ret){     //快速输出模版;
    if(ret>9)
    {
        out(ret/10);
    }
    putchar(ret%10+'0');
}

ll A[maxn],Amod[maxn];
ll poww(ll a,ll b){
    ll ans=1,base=a;
    while(b){
        if(b&1){
            ans*=base;
            ans%=mod;
        }
        b>>=1;
        base*=base;
        base%=mod;
    }
    return ans;
}

void init(){
    A[0]=1;
    Amod[0]=1;
    for(int i=1;i<=1e6+1;i++){
        A[i]=A[i-1]*i;
        A[i]%=mod;
        Amod[i]=poww(A[i],mod-2);
    }
}

int main(){
    init();
    int t,n,m;
    scanf("%d",&t);
    while(t--){
        read(n);
        read(m);
        if(m>=n){
            out(n);
            puts("");
            continue;
        }else{
            ll num=((A[n]*Amod[m])%mod*A[n-m])%mod;
            ll ans=((A[n+1]*Amod[m+1])%mod*A[n-m])%mod;
            ans=(ans*m)%mod;
            ans=(ans*poww(num,mod-2))%mod;
            out(ans);
            puts("");
        }
    }
    return 0;
}

新的开始,每天都要快乐哈!
在这里插入图片描述

你可能感兴趣的:(算法类)