您的位置:首页 > 其它

2013 多校第一场 hdu 4602 Partition

2013-07-23 21:02 393 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: