hdu 4982 Goffi and Squary Partition (想法题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4982

大致题意:题目首先给定了一个包含k个不同的正整数的集合,又定义了一个平方集合,一个数成为平方集合的条件有两个:

1.集合中k个数的和等于n

2.存在一个包含k-1个数的子集,满足这k-1个数的和等于一个数的平方(这个数可以任意取)

输入n,k问是否存在一个符合n,k的平方集合。

思路:

根据题目条件我们能很快的列出来两个方程:

1. a1+a2+a3+.......+ak=n

2. a1+a2+a3+.......+ak-1=x*x

所以有: 3.x*x=n-ak 此题的精髓就是集合包含的这k个数必须都是不同的。

根据3的公式我们可以把原问题转化成,x*x是否能由k-1个不含ak的数组成,比赛的时候就想到了这个地方的就进行不下去了。后来想到的方法就是先构造出k-1数使他们的和等于x*x的平方,再以这个解为基础看能否将其变化成满足题意的状态,如果可以则表示存在,如果不可以则表示不存在。

在构造的时候我们先让前k-2个数尽可能的小,我将它们取成1,2,3,4,.........,k-2,再将第k-1个数取成x*x与这k-2个数的差,如果ak-1是在1~ak-2之间的话,则不存在解,

如果ak>ak-2且ak不等于ak-1,则我们现在构建的这组解就是满足题意的。 如果ak<=ak-2则我们就需要来构建这组解。

构建解的方法是,将与ak相同的数取出,将其换成尽可能小的数,因为我们已经将前k-2个数取完了,所以这个最小的数只可能是k-1,计算出这个数的与ak的差作为增量,因为前ak-2个数都是相邻的,所以减少量只能由ak-1来提供,这是我们就判断一下ak-1能否提供这个与增量相同的减少量即可~~~~~


由于这种题也没有什么算法,我称作此类题为想法题~


code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <queue>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=10000;
const int MAX_N=1005;
const int MAX_K=3000;
const int MAXN=10010;

bool judge(int sum,int y,int k)
{
    int mid1=(k-1)*k/2;
    int mid2=sum-mid1;
    if(mid2<=k-1) return false;
    if(y>k-1&&y!=mid2) return true;
    if(y<=k-1){
        if(k-y<=mid2-(k+1)) return true;
        else return  false;
    }
    if(y==mid2){
        if(mid2-(k-1)>=3) return true;
        else return false;
    }

}

int main()
{
    int n,k,T,mm;
    bool flag;
    while(scanf("%d%d",&n,&k)!=EOF){
        int c1=(int)sqrt((double)k*(k-1)/2);
        int c2=(int)sqrt((double)n);
        flag=0;
        for(int i=c1;i<=c2;i++){
            if((k*(k-1)/2<=i*i)&&(i*i<=n-1)&&judge(i*i,n-i*i,k-1)){
                flag=1;
                break;
            }
        }
        if(flag==1) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值