这题应该属于组合数学,可以把一个数 n看成n个点然后可以从任意2个点之间的缝隙处分割因为n个点共有n-1条缝隙, 每个缝隙无非2种状态分割或不分割故所有的分割方案为2的n-1次方种方案,至于怎么根据分割算出题目要求的固定长度k在所有的方案中出现的次数,就简单了;可以这样想在所有方案中每个k出现的位置是不相同的(我说的位置不是第一个二个的位置,而是他在不同的分法序列中位置不同,即同一个序列中同一个位置不可能有2个k,不同分法中的k肯定不一样,故相对的位置也不一样),我们就根据这个位置的不同来枚举需要的结果数 要分3 中情况看 (一) 当k>=n 要么是0 要么是1,这个特判一下 (二)(1)不包含2个端点的点时,k的选法有 n-k-1种余下的缝隙有 n-k-2个 又由于每个缝隙都有2种状态 ,故此时的 方案数是(n-k-1)*2^(n-k-2) 种 (2) 是k包含2个端点之一时 k有2种选法 剩下的缝隙个数是 n-k-1 故方案数为2*2^(n-k-1) 合并(1)(2)就得到结果了
另外有于n较大故要用快速幂来算
#include<iostream>
long long const mod=1e9+7;
using namespace std;
long long quick_pow(int n)//快速幂
{
long long mul=2,ans=1;
while(n)
{
if(n%2)
ans=(ans*mul)%mod;
n/=2;
mul=(mul*mul)%mod;
}
return (ans%mod);
}
int main()
{
int T;cin>>T;
while(T--)
{
int m,k;cin>>m>>k;
if(k>m) cout<<0<<endl;
else if(k==m) cout<<1<<endl;
else
{
long long ans=quick_pow(m-k-2)*(m-k-1)+quick_pow(m-k);
cout<<ans%mod<<endl;
}
}
return 0;
}