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.
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).
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
貌似是个比较简单的规律题。
解题报告中说的很详细
我们可以特判出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;
}