2013 多校第一场 hdu 4602 Partition

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;
}


你可能感兴趣的:(2013 多校第一场 hdu 4602 Partition)