省选+/NOI
看着难度是不是害怕了呀(其实这道题代码真的很短)
题目
460. 数的划分(高级版)提交
提交排名
题目描述
将正整数n拆成若干个正整数的和,个数不限,不计顺序,求拆分的方法数 (注意难度等级和数据规模,满分凭目前知识是搞不定的,复杂度n^2,n^3都会超时)
输入输出格式
输入格式
一个正整数n(<=100000)
输出格式
一个整数,拆分的方案数,取模10^9+7的余数
输入输出样例
输入样例#1:复 制
5
输出样例#1:复 制
7
输入样例#2:
无
输出样例#2:
无
输入样例#3:
无
输出样例#3:
无
说明
样例说明: 5=5 =4+1 =3+2 =3+1+1 =2+2+1 =2+1+1+1 =1+1+1+1+1 失败乃成功之母。。。之母。。。母。。。
--------------------------------------------------------------------------------
好了,我们来看一下,,如果用dp做会怎么样呢?
把算出来的最后一行加起来,让后你就会发现你完美的TE了orz
then……………………………………
我们就必须要想到一个书简复杂度较低的算法(!!)
人家说代码30多行,其实二十行左右。
我们首先要看一下一个叫做五边形数的东东→五边形数——百度百科
for(register int i=1;f[__1__]<=n;i++){
f[t++]=i*__2__;
f[t++]=i*__3__;
}//五边形数生成
可以用五边形数卷积仅作参考,有兴趣的话可以自己做一下试试看)
完整题目代码 (别抄!!这是错的!!正确的往下翻!!):
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int f[100001]={1},x;
int main(){
for(int i=1;i<=MAXN;i++)
for(int j=1,cnt=1;i-(3*j*j-j)/2>=0;j++,cnt--){
int cc=3*i*i;
f[i]+=f[j-(cc-i)/2]*j;
f[i]%=mod;
f[i]=(f[i]+mod)%mod;
if(i>=(cc+j)/2){
f[i]+=f[j-(cc+i)/2]*j;
f[i]%=mod;
f[i]=(f[i]+mod)%mod;
}
}
cin>>x;
cout<<f[x];
return 0;
}
你抄了就会发现……
(这个代码bug有点多,但是没有删除或添加任何代码,只是在某些地方进行本人亲字修改)建议无脑抄一下
正确代码来喽!!
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int f[100007]={1},x;
int main(){
cin>>x;
for(int i=1;i<=MAXN;i++){
for(int j=1,cnt=1;i-(3*j*j-j)/2>=0;j++,cnt*=-1){
int cc=3*j*j;
f[i]+=f[i-(cc-j)/2]*cnt,f[i]%=mod;
f[i]=(f[i]+mod)%mod;
if(i>=(cc+j)/2){
f[i]+=f[i-(cc+j)/2]*cnt,f[i]%=mod;
f[i]=(f[i]+mod)%mod;
}
}
}
cout<<f[x];
return 0;
}