HDU 4602 Partition 数学水题...

题目大意:

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


你可能感兴趣的:(partition,HDU,4602)