2013 多校第一场 hdu 4602 Partition

来源:互联网 发布:求平年闰年的简便算法 编辑:程序博客网 时间:2024/05/24 01:18

hdu 4602

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4602

题目大意:将一个数 n 拆分,问所有的拆分组合中 K 出现了几次。

思路:我们可以特判出n<=k 的情况。对于 1<=k<=n-2 的情况,我们可以把 n 分解为n 个 1 ,即等效为n个点。利用隔板原理,在这N个点中,选出连续的 k 个点,以下分两种情况考虑:(1)被选出的点里不包含端点,那么总共有(n-k-1)种情况,剩下的(n-k)个点中总共有(n-k-2)个有效空隙,那么有(n-k-1)*2^(n-k-2)种方法。(2)被选出的点里包含端点,那么总共有2 种情况,剩下的点的有效空隙为(n-k-1)个,那么有2*2^(n-k-1)种方法。加起来总共是(n-k-1)*2^(n-k-2)+2*2^(n-k-1)种方法,化简一下就是(n-k+3)*2^(n-k-2)。上面是看了解题报告才写出来的,比赛的时候,貌似我们直接写了几个,然后YY 一下,写了个通项公式出来,再用矩阵过的。

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MOD  = 1e9+7;typedef __int64 lld;lld quick_mod(int a,int b){    lld  ans = 1;    while(b)    {        if(b&1)            ans = (ans*a)%MOD;        a = ((lld)a*a)%MOD;        b>>=1;    }    return ans;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,k;        scanf("%d%d",&n,&k);        if(k>n)        {            puts("0");            continue;        }        else if(k==n)        {            puts("1");            continue;        }        else if(k==n-1)        {            puts("2");            continue;        }        lld ans = ((n-k+3)*quick_mod(2,n-k-2))%MOD;        printf("%I64d\n",ans);    }    return 0;}