题目大意:
就是现在将一个数分成多个整数的和, 有很多种方式, 对于一个数n, 一共有f(n) = 2^(n - 1)中分割方式
例如n = 4
4 = 1 + 1 + 1 + 1
4 = 1 + 1 + 2
4 = 1 + 2 + 1
4 = 2 + 1 + 1
4 = 2 + 2
4 = 1 + 3
4 = 3 + 1
4 = 4
一共8中方式, 现在跟定n, k, 问在所有n的表达式中k这个数字出现了几次, 例如n = 4时, 4出现了1次, 1出现了12次
大致思路:
原本练习FFT的...结果挂错了把这个给挂上来了...
很简单的一个数学题, 首先将这个数分成n个1, , 那么考虑将其中连续的k个1连成一个k的种数, 当这k个数靠边时, 有2^(n - k - 1)种也就是f(n - k)种
当k个1在中间时, 左边有t1个1, 右边有t2个1时, 有f(t1)*f(t2)种也就是2^(t1 + t2 - 2) = 2^(n - k - 2)种
那么综上当n = k是有1个, 当n < k有0个
当n = k + 1时有两个, 当n > k + 1时有2^(n - k) + (n - k - 1)*(2^(n - k - 2))个
代码如下:
Result : Accepted Memory : 1584 KB Time : 15 ms
/*
* Author: Gatevin
* Created Time: 2015/7/15 14:52:46
* File Name: HDU4602.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
const lint mod = 1e9 + 7;
lint quick(lint base, int pow)
{
lint ret = 1;
while(pow)
{
if(pow & 1) ret = ret*base % mod;
pow >>= 1;
base = base*base % mod;
}
return ret;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, k;
scanf("%d %d", &n, &k);
if(n < k)
{
puts("0");
continue;
}
if(n == k)
{
puts("1");
continue;
}
if(n == k + 1)
{
puts("2");
continue;
}
lint tmp = quick(2LL, n - k - 2);
lint ans = (tmp*4LL + (n - k - 1)*tmp) % mod;
printf("%I64d\n", ans);
}
return 0;
}