2013 Multi-University Training Contest 5 Partition
思路:五边形数定理!!!
五边形数定理是一个由欧拉发现的数学定理,描述欧拉函数展开式的特性。欧拉函数的展开式如下:
亦即
欧拉函数展开后,有些次方项被消去,只留下次方项为1, 2, 5, 7, 12, ...的项次,留下来的次方恰为广义五边形数。
若将上式视为幂级数,其收敛半径为1,不过若只是当作形式幂级数(formal power series)来考虑,就不会考虑其收敛半径。
欧拉函数的倒数是分割函数的母函数,亦即:
其中为k的分割函数。
上式配合五边形数定理,可以得到
考虑项的系数,在 n>0 时,等式右侧的系数均为0,比较等式二侧的系数,可得
因此可得到分割函数p(n)的递归式
以n=10为例
这就是所求的了,当n<0时,p(n)=0;
p(n)的其他性质:
当限定将表示成刚好个正整数之和时,可以表示为。显然,。
- 对于,
- (OEIS:A004526)
- = 最接近的正整数。(OEIS:A069905)
代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<string> 7 #include<vector> 8 #define ll __int64 9 #define pi acos(-1.0) 10 #define MAX 100001 11 using namespace std; 12 const int mod=1000000007; 13 int an[MAX],n,t; 14 void init(){ 15 int i,j; 16 an[0]=an[1]=1; 17 an[2]=2;an[3]=3;an[4]=5; 18 an[5]=7; 19 for(i=6;i<MAX;i++){ 20 an[i]=0; 21 for(j=1;;j++){ 22 int g=j*(3*j-1)/2; 23 if(i-g<0) break; 24 if(j&1) an[i]+=an[i-g]; 25 else an[i]-=an[i-g]; 26 an[i]=an[i]%mod; 27 while(an[i]<0) an[i]+=mod; 28 g=j*(3*j+1)/2; 29 if(i-g<0) break; 30 if(j&1) an[i]+=an[i-g]; 31 else an[i]-=an[i-g]; 32 an[i]=an[i]%mod; 33 while(an[i]<0) an[i]+=mod; 34 } 35 an[i]%=mod; 36 } 37 } 38 int main(){ 39 init(); 40 scanf("%d",&t); 41 while(t--){ 42 scanf("%d",&n); 43 printf("%d\n",an[n]); 44 } 45 return 0; 46 }