背景
冬令营入学测试
描述
题目描述
小C是一名数学家,由于它自制力比较差,经常通宵研究数学问题。
这次它因为这个数学问题已经两天两夜没有睡觉了,再不研究出来就要出人命了!快帮帮它吧!
这个问题是这样的,有一个数n,将其拆分成若干自然数之和,要求乘积最大!
如果你以为问题仅仅这么简单,那你就太naive了。
由于小C挑战自己的自我修养,它规定分成的自然数两两之间一定不能相等!
它请你输出这个乘积最大是多少,但这个答案太大了,小C并没有兴趣看那么长的数字,它只想知道这个数对1000000007取模后的值是多少。
输入格式
一行一个数表示n
输出格式
一个数表示答案
备注
输入样例
6
输出样例
8
数据范围
对于30%的数据n<=10。
对于50%的数据n<=10000。
对于100%的数据1<=n<=1000000000。
30分暴力
#include<iostream> #include<cstdio> #define mod 1000000007 using namespace std; int n; long long ans; bool v[100001]; void dfs(int now,int remain,long long s)//now当前分出来的数,remain还剩下多少,s乘积 { if(remain==0) { ans=max(s,ans); return ; } for(int i=now+1;i<=remain;i++) { if(!v[i])//不能有重复 { v[i]=true; dfs(i,remain-i,s*i%mod); v[i]=false; } } } int main() { scanf("%d",&n); if(n==1)//1不用拆 { cout<<1; return 0; } dfs(0,n,1); if(ans==n) cout<<ans-1;//2、3、4的结果应该是1、2、3,但dfs结果是2,3,4,因为拆分成了0和本身。dfs时从1开始,所以2,3,4的0乘本身算成了本身。>4的数答案大于本身,所以不用管 else cout<<ans; }
AC做法:
#include<cstdio> #define mod 1000000007 using namespace std; int n,now=2,a[1000000],cnt; long long ans=1; int main() { scanf("%d",&n); if(n<=4) { printf("%d",n); return 0; } while(n>=now) { a[++cnt]=now; n-=now; now++; } if(!n) { for(int i=1;i<=cnt;i++) ans=a[i]%mod*ans%mod; printf("%d",ans); return 0; } int tot=cnt; while(n) { if(!tot) tot=cnt; a[tot--]++; n--; } for(int i=1;i<=cnt;i++) ans=a[i]%mod*ans%mod; printf("%d",ans); return 0; }