#hihocoder1372# 平方求和

题目1372:

平方求和

时间限制:1000ms
单点时限:1000ms
内存限制:256MB

描述

对于一个非负整数n,最少需要几个完全平方数,使其和为n?

输入

输入包含多组数据。对于每组数据:
第一行是n;如果n为-1,表示输入结束。(0 <= n <= 1000000001)

输出

针对每组数据,输出最少需要的完全平方数。

样例输入

3
4
5
-1

样例输出

3
1
2


解题:

一开始的思路:动态规划

结果:超空间

动态规划是很自然的想法,每个N都可能是一个平方a 和其它平方s的和组成,通过控制平方数a的大小,并利用之前已经得到的答案,选择其中的最小值作为N的答案。
但是很显然,1000000002*sizeof(short)远远超出了空间限制。
不过开始在没有别的好办法的情况下,我还是写了,至少得点基础分吧。

short *table = new short [max_n+1];
table[0]=0;
table[1]=1;
for(int i=2;i<=max_n;i++){
    short min_count=table[i-1]+1;
    for(int j=1;j*j<=i;j++){
        int new_count = table[i-j*j]+1;
        if(new_count<min_count)min_count = new_count;
    }
    table[i]=min_count;
}

苦思冥想后的意外收获:四方定理

一时间没想到好办法,用第一种方法打印了前1000个数的解。如图

220216164030306082.jpg

非常有规律啊,我不禁猜测可能最大的答案就是4。
然后按图索骥,我找到了

四方定理:
所有自然数至多只要用四个数的平方和就可以表示。

顺便贴一个证明:

http://planetmath.org/proofoflagrangesfoursquaretheorem

改进的思路:位运算

结果:超时间

有了四方定理,可以简化问题,只要不属于1、2、3,答案必定是4无疑。
然后考虑到空间不足。设计了新方案:
使用位运算,数字i能否被分解就由第i位来标记,1个、2个、3个平方和就需要三个变量,分别是once,twice,third

const int MAX_N = 1000000002;
class SpaceArray {
    public:
        bitset<MAX_N> once;//only for  query
        bitset<MAX_N> twice;
        bitset<MAX_N> third;
};

once时间复杂度: O(根号N)
twice需要once中标记为平方的位数,嵌套两次相加而得,时间复杂度为O(N)
third同理,需要once和twice里位数的和, O(N^(3/2))

注:把3个变量once、twice、third封装到class里,是为了 new 这个class,这种调用方式是在堆中分配内存,可以很大;相反,直接使用是在栈中调用,会报错-栈空间不够。
顺便复习了一下堆栈的知识,可怜我半吊子的C++水平。

最终的解决

放弃把表里每个值都求出来的思路了,现在只考虑输入的这个N;
采用方法:求根后取整再平方和原值比较。

bool check1(int number) {//是否一个平方组成
    int a = int(sqrt(number));
    return a*a == number;
}
bool check2(int number) {//是否两个平方和组成
    for (int i = 1, i2 = i*i; i2<number; i2+=(2*i+1), i++) {
        if (check1(number - i2))return true;
    }
    return false;
}
bool check3(int number) {//是否三个平方和组成
    for (int i = 1, i2 = i*i; i2<number; i2 += (2 * i + 1), i++) {
        if (check2(number - i2))return true;
    }
    return false;
}

根据四方定理,不是以上三者的都属于4个平方和可以组成的。
3个函数求值的时间复杂度如下
O(1)
O(N^1/2)
O(N)

一直WA的原因:0

开始一直以为输入0,输出也应该是0(0个完全平方的和是0)
走投无路,开始想各种可能性。结果这道题把0本身也看成是完全平方,无语。即 0 = 0 * 0,所以答案是1。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,712评论 0 33
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 昨天和婆婆关于孩子教育问题发生了争辩,争辩后的气氛有点尴尬,但也让我想明白了很多东西。 我们争辩的论点是,婆婆认为...
    Alpha_Mom阅读 317评论 0 1