hdu 4651 Partition (利用五边形定理求解切割数)

下面内容摘自维基百科:

五边形数定理[编辑]

五边形数定理是一个由欧拉发现的数学定理,描写叙述欧拉函数展开式的特性[1] [2]。欧拉函数的展开式例如以下:

亦即

欧拉函数展开后,有些次方项被消去,仅仅留下次方项为1, 2, 5, 7, 12, ...的项次,留下来的次方恰为广义五边形数

当中符号为- - + + - - + + .....

若将上式视为幂级数,其收敛半径为1,只是若仅仅是当作形式幂级数formal
power series
)来考虑,就不会考虑其收敛半径。

和切割函数的关系

欧拉函数的倒数是切割函数母函数,亦即:

当中为k的切割函数。

上式配合五边形数定理,能够得到

考虑项的系数,在
n>0 时,等式右側的系数均为0,比較等式二側的系数,可得

因此可得到切割函数p(n)的递归

以n=10为例

知道这个定理的话,hdu 4651就能够直接套模板了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define MP make_pair
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 100100;
const int INF = 0x3f3f3f3f;
const LL MOD = 1000000007;

int fiv[maxn];
LL p[maxn];

void init()
{
    int tot = 1;
    for(int i = 1; fiv[tot - 1] < maxn; i ++)///五边形数
    {
        fiv[tot ++] = i*(3*i-1)/2;
        fiv[tot ++] = i*(3*i+1)/2;
    }
    p[0] = 1;
    for(int i = 1; i < maxn; i ++)///i的切割数p(i)
    {
        p[i] = 0;int flag = 1;
        for(int j = 1; ; j ++)
        {
            if(fiv[j] <= i)
            {
                p[i] += flag * p[i - fiv[j]];
                p[i] = (p[i] % MOD + MOD) % MOD;
            }
            else break;
            if(j % 2 == 0) flag = -flag;
        }
    }
}

int main()
{
    int T, n;
    init();
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d", &n);
        printf("%lld\n", p[n]);
    }
}

hdu 4651 Partition (利用五边形定理求解切割数),布布扣,bubuko.com

时间: 2024-10-21 17:28:12

hdu 4651 Partition (利用五边形定理求解切割数)的相关文章

hdu 4651 Partition (利用五边形定理求解分割数)

以下内容摘自维基百科: 五边形数定理[编辑] 五边形数定理是一个由欧拉发现的数学定理,描述欧拉函数展开式的特性[1] [2].欧拉函数的展开式如下: 亦即 欧拉函数展开后,有些次方项被消去,只留下次方项为1, 2, 5, 7, 12, ...的项次,留下来的次方恰为广义五边形数. 其中符号为- - + + - - + + ..... 若将上式视为幂级数,其收敛半径为1,不过若只是当作形式幂级数(formal power series)来考虑,就不会考虑其收敛半径. 和分割函数的关系 欧拉函数的倒

HDU 4651 Partition 整数划分,可重复情况

Partition Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 842    Accepted Submission(s): 478 Problem Description How many ways can the numbers 1 to 15 be added together to make 15? The technical

hdu 4651 Partition——拆分数与五边形定理

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4651 参考:https://blog.csdn.net/u013007900/article/details/42365823 https://blog.csdn.net/visit_world/article/details/52734860 好像这样复杂度就是 \( O(n\sqrt{n} \) 的了. #include<cstdio> #include<cstring> #inclu

[ACM] hdu 3037 Saving Beans (Lucas定理,组合数取模)

Saving Beans Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold days. After some time the squirrel family thinks that they have to solve a probl

hdu 4704 费马小定理+快速幂

题意就是:做整数拆分,答案是2^(n-1) 由费马小定理可得:2^n % p = 2^[ n % (p-1) ]  % p 当n为超大数时,对其每个数位的数分开来加权计算 当n为整型类型时,用快速幂的方法求解 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const in

利用QR算法求解矩阵的特征值和特征向量

利用QR算法求解矩阵的特征值和特征向量 为了求解一般矩阵(不是那种幼稚到shi的2 x 2矩阵)的特征值. 根据定义的话,很可能需要求解高阶方程... 这明显是个坑...高阶方程你肿么破... 折腾了好久 1.我要求特征值和特征向量. 2.找到一种算法QR分解矩阵求解特征值 3.QR矩阵分解需要Gram-schimidt正交化分解 有一种很明显的感觉,往往在现在很难有 很系统 很深入 的学习某一个学科的某一门知识. 往往学的时候"靠,学这东西有什么用""学了这么久,也不知道怎么用,不想学" 到后

利用回溯法求解背包问题

最近看完了利用回溯法求八皇后问题,最后成功求解到92种解法,然后在看利用贪心求解背包问题,突然想到其实也可以利用回溯法求解背包问题,本质上回溯法是一个穷举的方式在求. 回溯法求解出的结果肯定是正确的,这也可以验证自己所写的贪心算法的正确性. 问题描诉: 设定Wmax为最大重量,W[](0~n-1)为编号0~n-1的货物重量,V[](0~n-1)为其价值,x[]为其中解, 在wn=ΣXi*Wi<Wmax的条件下,求Vmax=ΣXi*Vi. 代码如下: //全局变量最大价值int maxvalue=

利用数据结构栈求解迷宫问题

本段程序主要利用数据结构栈的先进后出特点,实现回溯求解迷宫路径问题. #include<iostream> #include<stack> using namespace std; //坐标类 struct Point { int x; int y; }; //地图类 template<int A> struct Map { int (*p)[A]; int row;//行数 int col;//列数 }; //start起始点, end终止点 template<

ACM:归并排序,以及利用归并排序思想求解逆序对数!

(一)归并排序 分析: (1)划分问题:把序列分成元素个数尽量相等的两半. (2)递归求解:把两半元素分别排序. (3)合并问题:把两个有序表合并成一个.(每次只需要把两个序列的最小元素加以比较,删除其中的较小元素并加入合并后的新表) #include <iostream> using namespace std; const int MAXN = 1000; int A[MAXN], T[MAXN]; void merge_sort(int *A, int x, int y, int *T)