UVALive

来源:互联网 发布:java 数字验证码识别 编辑:程序博客网 时间:2024/05/16 18:20

题意:给你A∈(a1,a2);B∈(b1,b2);C∈(c1,c2)和一个N
问有多少组A,B,C满足A+B+C=N。
挺繁琐的,由于数据范围有-1e9~1e9,不能暴力枚举,只能直接算。。。
为了方便思考,我们可以把A+B+C=N写成A+B=N-C。
这样枚举一下N-C的值就能发现规律了
ex: a=1~4 b=2~8 c=0~14 N=14
N-C的取值 ||||||||||||||||||||| C的取值 ||||||||||||||||||||| A,B的取值种类数
0 ||||||||||||||||||||||||||||||||||||||||||||14 ||||||||||||||||||||||||||||||||||||||||0
1 ||||||||||||||||||||||||||||||||||||||||||||13 ||||||||||||||||||||||||||||||||||||||||0
2 ||||||||||||||||||||||||||||||||||||||||||||12 ||||||||||||||||||||||||||||||||||||||||0
3 ||||||||||||||||||||||||||||||||||||||||||||11 ||||||||||||||||||||||||||||||||||||||||1//N-C=a1+b1
4 ||||||||||||||||||||||||||||||||||||||||||||10 ||||||||||||||||||||||||||||||||||||||||2
5 ||||||||||||||||||||||||||||||||||||||||||||9 ||||||||||||||||||||||||||||||||||||||||||3
6 ||||||||||||||||||||||||||||||||||||||||||||8 ||||||||||||||||||||||||||||||||||||||||||4//N-C=a2+b1
7 ||||||||||||||||||||||||||||||||||||||||||||7 ||||||||||||||||||||||||||||||||||||||||||4
8 ||||||||||||||||||||||||||||||||||||||||||||6 ||||||||||||||||||||||||||||||||||||||||||4
9 ||||||||||||||||||||||||||||||||||||||||||||5 ||||||||||||||||||||||||||||||||||||||||||4//N-C=a1+b2
10 ||||||||||||||||||||||||||||||||||||||||||4 ||||||||||||||||||||||||||||||||||||||||||3
11 ||||||||||||||||||||||||||||||||||||||||||3 ||||||||||||||||||||||||||||||||||||||||||2
12 ||||||||||||||||||||||||||||||||||||||||||2 ||||||||||||||||||||||||||||||||||||||||||1//N-C=a2+b2
13 ||||||||||||||||||||||||||||||||||||||||||1 ||||||||||||||||||||||||||||||||||||||||||0
14 ||||||||||||||||||||||||||||||||||||||||||0 ||||||||||||||||||||||||||||||||||||||||||0
很容易可以知道C固定后A,B的方案数有规律。。具体是先一个公差为1的等差数列,然后维持一段不变,然后再一个公差为-1的等差数列。图中已标出四个节点,分别是a1+b1,a2+b1,a1+b2,a2+b2。(a2+b1>=a1+b2如果不是swap一下)。然后根据C和N可知N-C的取值范围,在这段区间上求如上图右边这列数的和。。。
可计算上图的结果为28。
策略:暴力枚举N-C范围的所有情况分别算。。貌似有更简单写法。这样繁琐到吐血。
不要忘记取模和逆元。。
附上写的很挫的代码:

#include<bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define ll long long#define int ll#define INF 0x3f3f3f3f#define MAXN 2500010#define eps 1e-10#define COUT(x) cout<<x<<endlusing namespace std;const ll mod=1000000007;ll exgcd(ll a,ll b,ll &x,ll &y){    if(b==0){x=1,y=0;return a;}    else{ll q=exgcd(b,a%b,y,x);y=y-x*(a/b);return q;}}ll niyuan(ll a,ll n){    ll x,y;    ll d=exgcd(a,n,x,y);    if(d==1)        return (x%n+n)%n;    else        return -1;}main(){    int T,po[7];    scanf("%lld",&T);    int ks=1;    while(T--)    {        for(int i=0;i<7;i++)        scanf("%lld",&po[i]);        int a=po[0]+po[2],b=po[0]+po[3],c=po[1]+po[2],d=po[1]+po[3],cup=po[6]-po[4],cdown=po[6]-po[5];        if(b>c)            swap(b,c);        if(cup<a)        {            printf("Case #%lld: 0\n",ks++);            continue;        }        else if(cup<=b)        {//            COUT("b");            if(cdown>a)            {//                COUT("a");                printf("Case #%lld: %lld\n",ks++,((cup-a+cdown-a+2)*(cup-cdown+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else            {                printf("Case #%lld: %lld\n",ks++,((cup-a+1+1)*(cup-a+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }        }        else if(cup<c)        {//            COUT("c");            if(cdown<a)            {                printf("Case #%lld: %lld\n",ks++,((b-a+1+1)*(b-a+1)%mod*niyuan(2,mod)%mod+(cup-b)*(b-a+1)%mod)%mod);                continue;            }            else if(cdown<=b)            {                printf("Case #%lld: %lld\n",ks++,(((cdown-a+1)+(b-a+1))*(b-cdown+1)%mod*niyuan(2,mod)%mod+(cup-b)*(b-a+1)%mod)%mod);                continue;            }            else            {                printf("Case #%lld: %lld\n",ks++,(((cup-cdown+1)*(b-a+1)%mod))%mod);                continue;            }        }        else if(cup<=d)        {//            COUT("d");            if(cdown<a)            {                printf("Case #%lld: %lld\n",ks++,((b-a+1+1)*(b-a+1)%mod*niyuan(2,mod)%mod+(c-b-1)*(b-a+1)%mod+((d-cup+1)+(b-a+1))*(cup-c+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else if(cdown<=b)            {                printf("Case #%lld: %lld\n",ks++,(((cdown-a+1)+(b-a+1))*(b-cdown+1)%mod*niyuan(2,mod)%mod+(c-b-1)*(b-a+1)%mod+((d-cup+1)+(b-a+1))*(cup-c+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else if(cdown<=c)            {                printf("Case #%lld: %lld\n",ks++,(((c-cdown)*(b-a+1)%mod+((d-cup+1)+(b-a+1))*(cup-c+1)%mod*niyuan(2,mod)%mod))%mod);                continue;            }            else            {                printf("Case #%lld: %lld\n",ks++,((((d-cup+1)+(d-cdown+1))*((d-cdown+1)-(d-cup+1)+1)%mod*niyuan(2,mod)%mod))%mod);                continue;            }        }        else        {//            COUT("e");            if(cdown<a)            {                printf("Case #%lld: %lld\n",ks++,((b-a+1+1)*(b-a+1)%mod*niyuan(2,mod)%mod+(c-b-1)*(b-a+1)%mod+((d-c+1)+1)*(d-c+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else if(cdown<=b)            {                printf("Case #%lld: %lld\n",ks++,(((cdown-a+1)+(b-a+1))*(b-cdown+1)%mod*niyuan(2,mod)%mod+(c-b-1)*(b-a+1)%mod+((d-c+1)+1)*(d-c+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else if(cdown<=c)            {                printf("Case #%lld: %lld\n",ks++,(((c-cdown)*(b-a+1)%mod+((d-c+1)+1)*(d-c+1)%mod*niyuan(2,mod)%mod))%mod);                continue;            }            else if(cdown<=d)            {                printf("Case #%lld: %lld\n",ks++,((1+d-cdown+1)*(d-cdown+1)%mod*niyuan(2,mod)%mod)%mod);                continue;            }            else            {                printf("Case #%lld: 0\n",ks++);                continue;            }        }    }}I题没想法。。看了下别人的code居然是dijkstra写的。。完全想不到怎么用最短路做,先留坑,改日想想能不能补。。