2 2 4 2 22 4
NO YES YES
BestCoder 官方题解:
给你N和K,问能否将N拆分成K个互不相同的正整数,并且其中K-1个数的和为完全平方数 PS:这道题目原来是要求输出一种可行方案的,所以下面题解是按照输出方案的思想搞的。 分析: 我们尝试枚举那个完全平方数 S,然后看能否将他拆分为 K-1 个数,并且不用到N-S 这一步可以用贪心+一次调整来搞定。为了保证 K-1 个数都不同,我们尝试尽量用 1,2,3...这些连续自然数来构造,如果 N-S 出现在这些数中,那么将 N-S 移除,再新加一个数。如果这样都不能拆分成 K-1 个数,那么这个 S 肯定不行。 现在考虑已经用上述方法拆分了,我们需要判断这个拆分是否可行。会产生问题的只有最后一个数,这个数可能和 N-S 一样,也可能出现在之前的序列。如果是出现在之前的序列,那么这个拆分也是不靠谱的。如果和 N-S 一样,那么分两种情况 1. N-S 曾出现在之前的序列,那么显然这个拆分也是不靠谱的 2. N-S 比倒数第二个数大,对于这种我们可以通过调整最后一个数和倒数第二个数的大小,来使得这个拆分成立,假设最后一个数为 a,倒数第二个为 b,只要 a-1,b+1 就好了。当然如果 a-1 = b+1 这个拆分也是不靠谱的这道题目就这样搞定了,其实没必要找所有的完全平方数,只要找小于 N 与 N 最接近的完全平方数就好了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; int hash[1010]; int main() { for(int i=1;i<=1000;i++) hash[i]=i*i; int n,k; while(~scanf("%d%d",&n,&k)) { int sign=0; int m=(int)sqrt(n*1.0); if(m*m==n) m--; for(int i=m;i>=0;i--) { int p=hash[m]; int temp=n-p; int t=1; int xi=0; for(int j=1;j<k-1;j++)//开始构造k-1个数中的前k-2个 { if(t==temp)//与要去掉的那个数重合跳过 t++; p-=t; if(p<=t) { xi=1; break; } t++; } if(xi==0)//判断第k-1个数是否符合 { if(p==temp)//与要去掉的那个数重合 { p--; t++; } if(p<t)//第k-1个数在前面k-2个数中要没出现过 ; else { sign=1; } } } if(sign) printf("YES\n"); else printf("NO\n"); } return 0; }