sicily 1047(数学)

来源:互联网 发布:java 制作图片 编辑:程序博客网 时间:2024/05/22 08:22

题目链接:sicily 1047

解题思路:
题意很简单,即需要把一串连续的不超过25个的整数分成A、B两部分,分别相加得到两个数sumA、sumB,使得a+sumA=b+sumB。
一眼看过是感觉是0-1背包,但是其实不太一样,因为所有的整数是连续的,所以可以有更方便的方法解决。
假设第一个数为low,最后一个数为high,我们可以得到如下定理:
当A部分有 i 个数时,当且仅当(low+low+i-1)*i/2 <= sumA <= (high+high-i+1)*i/2时,存在满足题意的组合。
于是我们的算法就是枚举A部分有不同个数时,检查不等式组是否被满足。注意首先需要判断a+sumA+b+sumB是否为偶数,并且sumA与sumB不能为负数,详见代码。

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int a,b,low,high;int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d %d %d %d",&a,&b,&low,&high);        if(b<a){            swap(a,b);        }        int flag=0,sum=a+b,tmp;        sum += (low+high)*(high-low+1)/2;        tmp = sum/2;        if(sum%2==0&&tmp>=a)        {            tmp -= a;            for(int i=0;i<=high-low+1;i++)            {                int low_val = (low+low+i-1)*i/2, high_val = (high+high-i+1)*i/2;                if(tmp>=low_val&&tmp<=high_val){                    flag=1;                    break;                }            }        }        if(flag)            printf("possible\n");        else            printf("not possible\n");    }    return 0;}

总结:
好题!懂得复杂算法之后不能忽视问题中的数学属性。

0 0
原创粉丝点击