题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=530

(格式有一点点问题,直接粘下来吧)

题目意思:给出 n 和 k,问能否构造 k-1个不同的数使得这 k-1 个数(每个数都为正整数)的和等于一个数的平方,且 k 个数(都为正整数)的和等于 n。

错了差不多十多次,终于要看别人思路了.......

为了将问题简化,且保证 k-1 个数都是不同的,我们从自然数1,2,...,k-2 构造出前 k-2 个数,看清楚,不是 k-1 而是 k-2。因为最后第 k-1 个数有待斟酌!!!

设 square 为 k-1 个数之和,也就是等于的某个数的平方啦,remain 就是 n - square了。

先排除两种特殊情况:

(1) remain = 0 (不符合正整数的要求)或者 (k-1) * k /2 > square(因为是从1开始构造的,最小的square 都需要大于等于 (k-1)* k /2(1+2+3+...+k-1) ,避免无谓的计算

  (2)如果square = 1 并且 remain = 1 ,那么无解。这就是Sample 中的2 2了。

然后开始构造k-2个数。构造的时候,如果遇到remain(假如为x),就跳过一位,变成x+1,使得构造的数中不包含remain。因此代码中就有 x 多自增1次的操作了。

构造完 k-2 个数之后(设和为sum),我们要对最后一个数,即第 k-1个数进行讨论(代码中的need,它的值等于 n - sum - remain)。如果这个 need <= x (第 k-2 个数的值就是x),代表 k - 1个数中有两个数是相同的,与题意不符。而且它就算怎样调整都不能构造出答案,因为我们是从最小的自然数1开始构造的!

比较难理解的是,最后的那个k-1的数,我们还是x++,但是sum + x 有可能并不等于 (确切来讲是小于,如果是大于都是无解的,从最小数开始构造嘛)square,但是我们可以调整 k-2个数中的某个数ai令它大点--->ai+k,使得sum + x(此时的x不是原来单纯的 x++ 了,x = square-(sum-ai+ai+k)) 不过这些情况比较复杂,所以我们反其道而行之,讨论无解的情况!

无解的时候,有两种情况。最后 前面不是说 x++ 吗,那么第一种肯定无解的情况:x == remain && need == remain!这个表示remain 在k-2个数的构造中根本没有遇到。而且need这个值 是必须的,无论前面怎样调整,还是那个道理,从最小数1开始构造。

最难理解的是第二种情况 x+1 == remain && need == remain (我也想了好久才想通,wa了这么多次就是这个没想出来)。remain 是动不了的,只能从need 和 前面已经构造了的 k-2个数中开刀。

我们不希望need = remain,于是只能让k-2个数中的某个数增加1(确切来讲只能是黑色字体的x,因为数与数之间是紧挨着的),变成蓝色部分的x++,此时need 确实不等于 remain,但是need 却等于蓝色部分的x++(need - 1)了,也就是最后构造出来的k-1 个数中有两个数是相同的!!!

只要排除这两种情况,就表示可以得出解。

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std; int n, k; bool check(int square, int remain)
{
if (remain == && square == ) // k = 2, remain = 1的情况
return false;
int sum = ;
int x = ;
for (int i = ; i < k-; i++) // 构造k-2个数
{
x++;
if (x == remain)
x++;
sum += x;
}
int need = n-sum-remain;
if (need <= x) // 最后第k-1个数在前k-2个已构造数里面
return false;
// need > x(未自增前),有可能与remain有冲突(remain在k-2个数之外)
x++;
if (x == remain || x + == remain)
{
if (need == remain) // need == remain == x
return false; // or need == remain == x+1
}
return true; // need > x+1
} int main()
{
while (scanf("%d%d", &n, &k) != EOF)
{
int flag = ;
for (int i = ; i * i < n && !flag; i++)
{
int square = i*i;
int remain = n - square;
if (remain == || (k-)*k/ > square)
continue;
if (check(square, remain))
{
flag = ;
break;
}
}
printf("%s\n", flag ? "YES" : "NO");
}
return ;
}

BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告的更多相关文章

  1. BestCoder22 1002.NPY and arithmetic progression(hdu 5143) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5143 题目意思:给出 1, 2, 3, 4 的数量,分别为a1, a2, a3, a4,问是否在每个数 ...

  2. BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5087 题目意思:找出第二个最长递增子序列,输出长度.就是说,假如序列为 1 1 2,第二长递增子序列是 ...

  3. HDU 4982 Goffi and Squary Partition(推理)

    HDU 4982 Goffi and Squary Partition 思路:直接从全然平方数往下找,然后推断是否能构造出该全然平方数,假设能够就是yes,假设都不行就是no.注意构造时候的推断,因为 ...

  4. hdu 4982 Goffi and Squary Partition

    Goffi and Squary Partition Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Subm ...

  5. hdu4982 Goffi and Squary Partition (DFS解法)

    BestCoder Round #6 B http://acm.hdu.edu.cn/showproblem.php?pid=4982 Goffi and Squary Partition Time ...

  6. 【HDOJ】4982 Goffi and Squary Partition

    题意就是整数划分,选出和为n的K个整数,其中K-1个数的和为完全平方数S.选择整数时需要从1,2,3..连续选择,当选择整数与n-S相等时,需要跳过n-S,即选择n-S+1.如此选择K-2个数,从而可 ...

  7. Goffi and Squary Partition

    题意: 给你N和K,问能否将N拆分成K个互不相同的正整数,并且其中K-1个数的和为完全平方数. PS:这道题目原来是要求输出一种可行方案的,所以下面题解是按照输出方案的思想搞的. 分析: 我们尝试枚举 ...

  8. BestCoder20 1002.lines (hdu 5124) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 题目意思:给出 n 条线段,每条线段用两个整数描述,对于第 i 条线段:xi,yi 表示该条线段 ...

  9. BestCoder18 1002.Math Problem(hdu 5105) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5105 题目意思:给出一个6个实数:a, b, c, d, l, r.通过在[l, r]中取数 x,使得 ...

随机推荐

  1. Play框架连接Mysql遇到的一些问题

    最近,在基于Play框架的项目中需要连接Mysql数据库.在这个过程中遇到了一些问题.在此,把它记录下来. 首先,Play框架和Mysql连接有两种方式,这两种方式都是在application.con ...

  2. input 对伪元素(:before :after)的支持情况

    最近做一个自定义视觉效果的Switch组件,用到了 input:radio 和 label,并在label里用伪元素 :before 模拟状态的切换效果. 但是同事评审的时候说可以不用label,直接 ...

  3. openfire Android学习(一)----实现用户注册、登录、修改密码和注销等

    以前学习过用Scoket 建立聊天,简单的建立聊天是没问题的,但如果要实现多人复杂的聊天,后台服务器代码就比较复杂,对于我这新手来讲就比较难了.后来在网上看到用openfire做服务器,利用强大的Sm ...

  4. php命令行查看扩展信息

    通常,在php的开发过程中,我们会使用到第三方扩展,这时候,我们对于php扩展的信息的查看就显得尤为重要了.一般情况下,我们查看到扩展信息,都是直接通过 cat *.ini  文件来进行,这样子的效率 ...

  5. UnicodeEncodeError: 'ascii' codec can't encode character u'\u5728' in position 1

    s = "图片picture"print chardet.detect(s) for c in s.decode('utf-8'): print c UnicodeEncodeEr ...

  6. iOS开发 Coretext基本用法

    转至 http://blog.csdn.net/fengsh998/article/details/8691823 API接口文档. https://developer.apple.com/libra ...

  7. Git以及github的使用方法(六),管理修改

    现在,假定你已经完全掌握了暂存区的概念.下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件. 你会问,什么是修改?比如你新增了一行,这就是一个修改 ...

  8. react request.js 函数封装

    1.request.js  函数封装 import { Toast } from 'antd-mobile'; import axios from 'axios'; import store from ...

  9. 【转载】读懂IL代码就这么简单(三)完结篇

    一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认为 ...

  10. nodejs REPL(交互式解释器)

    Node.js REPL(交互式解释器) Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Window 系统的终端或 Unix/Linux ...