太戈编程460

本文探讨了一道高级版的数的划分问题,指出常规的动态规划方法会导致超时。作者引导读者了解如何利用五边形数来降低时间复杂度,并提供了含有错误的示例代码,随后给出了修正后的正确代码。通过这种方法,解决了在限定时间内求解正整数n的不同划分方法数的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

省选+/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;
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值