ZOJ 3685 ZJU2013年01月月赛J题 Cube

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3685

这道题刚开始想了其他很多思路,包括DP什么都没有头绪。当时还有40多分钟,就想要专心过这题了。

然后就写了复杂度为O(2^n)的程序,算出了前25个之后,发现从第15个开始,答案不是0就是1。

分析一下可以发现,改变正负号不改变结果奇偶性,当1 ~ n中奇数为奇数个时,答案就为奇数,不然就是偶数。

可以计算得到1^3 + 2^3 + ... + n^3 = n^2 * (n+1)^2 / 4

如果n>=15时,假如答案不是0就是1这点成立,等价于从1^3 , 2^3 , 3^3 , ... , n^3中选取一些数字,使得和为 n^2 * (n+1)^2 / 8(取整)有解。

整数拆分问题!!当然不能用dp的方法做,抱着试试的心理写了裸的dfs,然后就过了。这应该是说明解的数量非常多吧。

n<15的所有情况,都可以暴力枚举算出来,我直接打表写在程序里了。

当然,我现在无法证明,为什么大于14的时候一定会有解,找到的话,会添加到这里。 

代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 typedef long long ll;
 5 const char ans[20][20]={
 6 "",
 7 "+",
 8 "-+",
 9 "-++",
10 "-+++",
11 "-++++",
12 "-+++-+",
13 "+---+++",
14 "+--+--++",
15 "+--+-+--+",
16 "-+-+++++++",
17 "-++-+--++++",
18 "+--++---+-++",
19 "--+++++-+++++",
20 "-++-+--++--+-+"
21 };
22 char s[10010];
23 ll s3[10010];//预处理三次方
24 bool dfs(ll sum,int n){
25     for(int i=n;i>0;i--)if(sum>=s3[i]){
26         if(sum - s3[i]==0 || dfs(sum - s3[i],i-1)){
27             s[i-1]='+';
28             return true;
29         }
30     }
31     return false;
32 }
33 void solve(ll n){
34     for(int i=0;i<n;i++)s[i]='-';
35     ll sum=n*n*(n+1)*(n+1)/8;
36     dfs(sum,n);
37     for(int i=n-1;i>=0;i--)putchar(s[i]);
38     puts("");
39 }
40 int main()
41 {
42     for(ll i=1;i<=10000;i++) s3[i]=i*i*i;
43     int n;
44     while(~scanf("%d",&n)){
45         if(n<15)puts(ans[n]);
46         else solve(n);
47     }
48     return 0;
49 }

做这场月赛的时候在最后两分钟,调出来过了,绝杀。。爽

原文地址:https://www.cnblogs.com/hundundm/p/2870202.html