题目大意:
就是现在将一个数分成多个整数的和, 有很多种方式, 对于一个数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; }