题面大意 给定n,k问是否有k个不同正整数 和为n 且其中k-1个数 是某个数的平方数
设 k-1个数等于 i²,每次从大到小枚举i,看是否存在合法的,由于k个数 必须不同,所以 出来k-1个数 剩下一个数 z=n-i²。当z>k时 k-1个数从1 到k-1 排列,只要比i²小,比i²小的部分 可以从大到小 不断加一的方式 来完美的 凑出所以比 k(k-1)/2大的所有数。但当z=k时,k-1个数从1 到k-1 排列,由于不能和已经确定的z值冲突,无法形成 比k(k-1)/2正好大一的数 ,特判下即可。z<k时,把z混到k中即可。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include<stack>
#include<bitset>
#define inf 0x3f3f3f3f
#define ll long long
#define mod 1000000007
using namespace std;
#define bug puts("bugbugubgbugbug");
int go(int n,int m,int z)
{
if(z<=0)return 0;
if(z>m)
{
m--;
if(m*(m+1)/2<=n-z)
return 1;
return 0;
}
else
{
if(z==m)
{
if(m*(m+1)/2==n-1)
return 0;
}
if(m*(m+1)/2<=n)
return 1;
return 0;
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int flag=0;
int z=sqrt(n);
while((z+1)*(z+1)<=n)z++;
for(int i=z;i>=1;i--)
if(go(n,m,n-i*i))
{
flag=1;
break;
}
if(flag)puts("YES");
else puts("NO");
}
}