HDU 4602 Partition (整数拆分&找规律&快速幂取模)

59 篇文章 0 订阅
49 篇文章 0 订阅

Partition



Time Limit: 2000/1000 MS (Java/Others)    

Memory Limit: 32768/32768 K (Java/Others)



Problem Description
Define f(n) as the number of ways to perform n in format of the sum of some positive integers. For instance, when n=4, we have
  4=1+1+1+1
  4=1+1+2
  4=1+2+1
  4=2+1+1
  4=1+3
  4=2+2
  4=3+1
  4=4
totally 8 ways. Actually, we will have f(n)=2 (n-1) after observations.
Given a pair of integers n and k, your task is to figure out how many times that the integer k occurs in such 2 (n-1) ways. In the example above, number 1 occurs for 12 times, while number 4 only occurs once.
 

Input
The first line contains a single integer T(1≤T≤10000), indicating the number of test cases.
Each test case contains two integers n and k(1≤n,k≤10 9).
 

Output
Output the required answer modulo 10 9+7 for each test case, one per line.
 

Sample Input
  
  
2 4 2 5 5
 

Sample Output
  
  
5 1


1. 观察发现n的分拆中n出现了1次,n-1出现了2次,n-2出现了5次,……,这一发现是否正确?

这样想:n出现了1次不用说;n-1出现了2次是因为剩下那个数是1,它只能和n-1有两种组合,或者当n=2时变成1+1,那也有2个数;n-2出现了5次是因为剩下的数2可以与n-2有3+2种组合,……


那么,记a1=1,a2=2,a3=5,...,我们的目标就是求出an


2. 如何求出an

利用公式:an=Sn-Sn-1


3. 如何求出Sn

考虑将n分成k个正数,由插空法知有C(n-1,k-1)种分法(或者:这等价于方程x1+x2+...+xk = n-k的非负解的个数,亦等价于从k种不同的物品中允许重复地选出n-k个物品的方法数),于是求出总个数Sn


4. 注意n,k可能较大,要使用快速幂取模。

完整代码:

/*31ms,228KB*/

#include<cstdio>
const int mod = 1000000007;

__int64 pow(__int64 a, __int64 b)///a^b % mod
{
	__int64 r = 1, base = a;
	while (b)
	{
		if (b & 1)
			r = r * base % mod;
		base = base * base % mod;
		b >>= 1;
	}
	return r;
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, k;
		scanf("%d%d", &n, &k);
		if (k > n)
			puts("0");
		else
		{
			int temp = n + 1 - k;
			if (temp == 1)
				puts("1");
			else if (temp == 2)
				puts("2");
			else
				printf("%I64d\n", (temp + 2) * pow(2, temp - 3) % mod) ;
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值