sicily 1047(数学)

题目链接: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;
}

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

你可能感兴趣的:(sicily 1047(数学))