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
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
自己写几个数会发现一个规律!!
会打出一个表格:
1 2 3 4 5
1 1 0
0 0 0
2 2 1
3 5 2 1
4 12 5 2 1
5 28 12 5 2 1
呵呵,发现对角线的数是相同的吧!还有竖着是不是 a[n]=a[n-1]*2+2^(n-2)呢!!
聪明,现在就运用高中的知识就能求出a[n]的通项了。a[n]=(n-3)*2^(n-2);到此以成功
一大半了,接下来就用一个2的快速幂,不然会超时!!
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <string>
#include <stack>
#include <cctype>
using namespace std;
__int64 exp_mod(__int64 a,__int64 n,__int64 b)
{
__int64 t;
if(n==0) return 1%b;
if(n==1) return a%b;
t=exp_mod(a,n/2,b);
t=t*t%b;
if((n&1)==1) t=t*a%b;
return t;
}
int main()
{
int t;
__int64 n,m;
scanf("%d",&t);
while(t--)
{
scanf("%I64d%I64d",&n,&m);
__int64 temp;
if(m>n)
printf("0\n");
else{
temp=n-m;
if(temp==0)
printf("1\n");
else if(temp==1)
printf("2\n");
else
{
__int64 ans;
ans=(temp+3)*exp_mod(2,temp-2,1000000007)%1000000007;
printf("%I64d\n",ans);
}
}
}
return 0;
}