#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 1000000007
__int64 getpow(__int64 x,int n){
__int64 temp=1;
while(n){
if(n&1) temp*=x;
temp%=inf;
n/=2;
x*=x;
x%=inf;
}
return temp%inf;
}
int main(){
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(m==n){
printf("1\n");
continue;
}
if(m>n){
printf("0\n");
continue;
}
if(m+1==n){
printf("2\n");
continue;
}
printf("%I64d\n",((getpow(2,n-m-2)%inf)*((n-m+3)%inf))%inf);
}
return 0;
}
分析:
当n=4的时候所有情况题上以给出
当n=5的时候:
1+1+1+1+1
2+1+1+1
1+2+1+1
1+1+2+1
1+1+1+2
2+3
3+2
1+2+2
2+1+2
2+2+1
3+1+1
1+3+1
1+1+3
4+1
1+4
5
所以n-m
5-5 1
5-4 2
5-3 5
5-2 12
5-1 28
在根据n=4,n=3会发现总是1 2 5 12 28。。。。。
发现f[n+1]=2*f[n]+2^(n-1)
这就是一道高中的求通项公式的题目了,公式两边同时处以2^(n+1)
就构造了一个以f[n]/(2^n)为通项,1/4为公差的等差数列,数列首项是2/2=1;
所以f[n]/(2^n)=(n+3)/4
所以f[n]=(n+3)*2^(n-2)
当然这里的n指的是题目中的n-m。。。首项就是2,这是需要说明的。。因为公式不能由前面推出第一项。。
还有一点需要注意的是:必须要用快速幂模,不然会超时。。。还需要用__int64因为中间的乘积可能超过int范围。