Partition
题目连接:Click here~~~~
Problem Description
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.
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.
2
4 2
5 5
Sample Output
5
1
正如题中所说,每次都要把所有的等式写出来,然后在数出每个数字出现的次数,这就提示我们每个数字出现的次数必然是有关系的,或者可以这样说,是有公式或规律的。下面大家可以看一下6以内每个数字出现次数:
1:64 a6
2:28 1:28 a5
3:12 2:12 1:12 a4
4: 5 3: 5 2: 5 1: 5 a3
5: 2 4: 2 3: 2 2: 2 1: 2 a2
6: 1 5: 1 4: 1 3: 1 2: 1 1: 1 a1
不难发现,从第三项开始满足 a3 = 2*a2+2^0,a4 = 2*a3+2^1,a5 = 2*a4+2^2,a6 = 2*a5+2^3,那么将其全部转化为有关 a2 的等式,然后将 a2 = 2 代入,那么为
a3 = 2 ^ 2 + 2^0,
a4 = 2 ^ 3 + 2 * 2^1,
a5 = 2 ^ 4 + 3 * 2^2,
a6 = 2 ^ 5 + 4 * 2^3,
*******
an = 2 ^ ( n-1 ) + ( n-2 ) * 2 ^ ( n-3 ) =( n+2 ) *2 ^ ( n-3 ) ;
又发现,求 n 中的第 k 个数字,相当于求 a ( n-k+1) 的值,则将式中的 n 换为 n-k+1 即可。即公式为( n-k+3 ) * 2 ^ ( n-k-2 ) ;另外,还要考虑 n<k 的情况,且还要用到二分幂。具体代码如下:
#include<stdio.h>
__int64 M = 1e9 + 7 ;
__int64 fun1(__int64 b)
{
__int64 x, sum;
if(b == 1 || b == 0) return 2;
x = fun1 (b / 2);
sum = (x%M) * (x%M) % M;
if(b%2) sum = sum * 2 % M;
return sum;
}
int main()
{
__int64 N;
__int64 m,n,a,b;
scanf("%I64d",&N);
while(N--)
{
scanf("%I64d%I64d",&m,&n);
if(m<n) {printf("0\n");continue;}
if(m==n) {printf("1\n");continue;}
if(m-n==1) {printf("2\n");continue;}
if(m-n==2) {printf("5\n");continue;}
a = fun1( m - n - 2);
b = (m - n + 3) * a % M;
printf("%I64d\n",b);
}
}