您的位置:首页 > 其它

hdu - 4602 - Partition(快速幂)

2013-07-24 16:51 441 查看
题意:将一个整数n分拆成小于或等于它的正整数相加,共有2^(n-1)种拆法,问在所有的拆法中,数字k出现的次数(1 <= n, k <= 1000000000,共有T(1 <= T <= 10000)组测试数据),结果模1000000007。

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

——>>三种情况:

1、当k > n时,结果为0;

2、当k == n时,结果为1;

3、当k < n时,把n分成n个1,要取出k个连续的1组成1个k,设取出来的这k个1的第一位是b,则b的左边有b-1个1,根据题意得,将b-1分拆共有2^(b-2)种拆法,[b, b+k-1]是取的连续的1,它的右边还有n - (b+k-1)个1,n - (b+k-1)有2^[n - (b+k-1) - 1] = 2^(n-b-k)种拆法,所以,当取定这个位置的k时,有2^(b-2) *  2^(n-b-k) = 2^(n-k-2)种情况(发现与b无关),这里没有重复,因为计算每个位置的k只计算他自己一次,而不管其他地方是否也出现了k。

当b == 1时——>b的左边没有1,右边——>2^(n-b-k) = 2^(n-1-k);

当b == n-k+1时——>组成的k的右边没有1,左边——>2^(b-2) = 2^(n-1-k);

当2 <= b <= n-k时——>就有(n-k-2+1) * 2^(b-2) *  2^(n-b-k);

总共就是2^(n-b-k) + 2^(n-1-k) + (n-k-2+1) * 2^(b-2) *  2^(n-b-k) =
(n-k+3)*2^(n-k-2)。

由于指数大,应用快速幂。

#include <cstdio>

using namespace std;

const int mod = 1000000000 + 7;

int pow_mod(int n)
{
if(n == 0) return 1;
if(n == 1) return 2;
int x = pow_mod(n / 2);
long long ans = (long long)x * x % mod;
if(n % 2 != 0) ans = ans * 2 % mod;
return (int)ans;
}

int main()
{
int T, n, k, ret;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &k);
if(k > n) ret = 0;
else if(k == n) ret = 1;
else if(k == n-1) ret = 2;
else ret = (int)((long long)(n - k + 3) * pow_mod(n - k - 2) % mod);
printf("%d\n", ret);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: