HDU 4602 Partition 组成n的方案中k有几个 (好题!!!!找规律题+快速幂)

来源:互联网 发布:js date 设置日期 编辑:程序博客网 时间:2024/05/23 07:24

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≤109).
 

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

Sample Input
24 25 5
 

Sample Output
51



貌似是个比较简单的规律题。 

解题报告中说的很详细

我们可以特判出n <= k的情况。 
对于1 <=  k < n,我们可以等效为 n个点排成一列,并取出其中的连续k个点。下面分两种
情况考虑: 
第一种情况,被选出的不包含端点,那么有(n – k − 1)种情况完成上述操作,剩下未被圈的点
之间还有(n – k − 2)个位置,可以在每个位置断开,所以共 2^(n−k−2) ∗ (n−k−1)种方法。 
第二种情况,即被选出的包含端点,那么有2 种情况,并且剩余共(n – k − 1)个位置,所以共
2 ∗ 2^(n – k − 1)种方法。 
总计2 ∗ 2^(n – k − 1) + 2^(n – k − 2) ∗ (n – k − 1) = (n – k + 3) * 2^(n – k − 2)。 


这里为什么要分成两种情况呢? 其实想一下就明白了, 如果你选的这K个点包含了端点, 那么剩余的部分和这部分之间就一个空位隔开, 如果不包含端点,那就会有两个空位隔开了。这两种的计算肯定是不一样的。



#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const LL mod = 1e9+7;LL pow_mod(LL x,LL n){LL res=1;while(n>0) {if(n&1) res=res*x%mod;x=x*x%mod;n=n>>1;}return res;} int main(){int t;LL res,k,n;cin>>t;while(t--) {cin>>n>>k;if(k>n) {printf("0\n");continue;}res=2*pow_mod(2,n-k-1)%mod+(n-k-1)*pow_mod(2,n-k-2)%mod;cout<<res%mod<<endl;}return 0;}






0 0