BZOJ2661: [BeiJing wc2012]连连看

Time Limit: 10 Sec  Memory Limit: 128 MB
Description

 凡是考智商的题里面总会有这么一种消除游戏。不过现在面对的这关连连看可不是QQ游戏里那种考眼力的游戏。我们的规则是,给出一个闭区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x2-y2是一个完全平方数z2,并且y与z互质,那么就可以将x和y连起来并且将它们一起消除,同时得到x+y点分数。那么过关的要求就是,消除的数对尽可能多的前提下,得到足够的分数。快动手动笔算一算吧。

Input

        
 只有一行,两个整数,分别表示a,b。

Output

 两个数,可以消去的对数,及在此基础上能得到的最大分数。

Sample Input

1 15

Sample Output

2 34

HINT

对于30%的数据,1<=a,b<=100

对于100%的数据,1<=a,b<=1000

/**************************************************************

    Problem: 2661

    User: ictsing

    Language: C++

    Result: Accepted

    Time:200 ms

    Memory:79464 kb

****************************************************************/

 

//BZOJ2661 [BeiJing wc2012]连连看

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <cmath>

#include <queue>

using namespace std;

const int inf = 1000000000;

int ans1=0,ans2=0;

const int mt = 2000+5;

const int mm = 2000000+5;

int cap[mm<<1],cost[mm<<1],adj[mt],fr[mm<<1],to[mm<<1],nxt[mm<<1];

int ecnt=1;

int dis[mt<<1],cur[mt];

bool inq[mt];

int s=0,t=2000+3;

queue<int>q;

inline int read()

{

    int num=0,flag=1;

    char ch;

    do{

        ch=getchar();

        if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

        num=num*10+ch-'0';

        ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

int gcd(int a,int b)

{

    if(b==0) return a;

    return gcd(b,a%b);

}

bool judge(int x,int y)

{

    if(x<y) swap(x,y);

    int zz=x*x-y*y;

    int tmp=sqrt(zz);

    if(tmp*tmp==zz&&gcd(x,y)==1) return true;

    return false;

}

void adde(int u,int v,int cc,int ccc)

{

    ecnt++,fr[ecnt]=u,to[ecnt]=v,nxt[ecnt]=adj[u],cap[ecnt]=cc,cost[ecnt]=ccc,adj[u]=ecnt;

    ecnt++,fr[ecnt]=v,to[ecnt]=u,nxt[ecnt]=adj[v],cap[ecnt]=0,cost[ecnt]=-ccc,adj[v]=ecnt;

}

bool spfa()

{

    while(!q.empty()) q.pop();

    for(int i=s;i<=t;i++) dis[i]=-inf,inq[i]=0;

    q.push(s),dis[s]=0,inq[s]=1;

    while(!q.empty())

    {

        int u=q.front();q.pop();inq[u]=0;

        for(int i=adj[u];i;i=nxt[i])

        {

            int v=to[i];

            if(dis[v]<dis[u]+cost[i]&&cap[i])

            {

                dis[v]=dis[u]+cost[i];cur[v]=i;

                if(!inq[v]) inq[v]=1,q.push(v); 

            }

        }

    }

    return dis[t]!=-inf;

}

void mcf()

{

    while(spfa())

    {

        int tmp=inf;

        for(int i=cur[t];i;i=cur[fr[i]]) tmp=min(tmp,cap[i]);

        ans2+=dis[t]*tmp;

        for(int i=cur[t];i;i=cur[fr[i]]) cap[i]-=tmp,cap[i^1]+=tmp;

    }

}

int main()

{

    int a=read(),b=read();

    for(int i=a;i<=b;i++)

        for(int j=a;j<=b;j++)

        {

            if(judge(i,j)&&i!=j)

            {

                adde(i,j+1000,1,i+j);

            }

        }

    for(int i=a;i<=b;i++)

        adde(s,i,1,0),adde(i+1000,t,1,0);

    mcf();

    for(int i=2;i<=ecnt;i+=2)

        if(to[i]==t&&!cap[i]) ans1++;

    printf("%d %d\n",ans1/2,ans2/2);

    return 0;

}

 


评论

热度(5)