hdu 4602 partition 2013多校联合训练第一场

这题应该属于组合数学,可以把一个数 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;
}


 

 

你可能感兴趣的:(partition,HDU,4602,2013多校联合训练第一场)