2015 Multi-University Training Contest 5(hdu5343 - 5352)网络流+yy+(哈夫曼树+dp)

来源:互联网 发布:ubuntu 反应慢 编辑:程序博客网 时间:2024/06/07 17:36

MZL’s xor

Problem Description

MZL loves xor very much.Now he gets an array A.The length of A is n.He wants to know the xor of all (Ai+Aj)(1i,jn)
The xor of an array B is defined as B1xorB2...xorBn

Input
Multiple test cases, the first line contains an integer T(no more than 20), indicating the number of cases.
Each test case contains four integers:n,m,z,l
A1=0,Ai=(Ai1m+z)modl
1m,z,l5105,n=5105

Output
For every test.print the answer.

Sample Input

2
3 5 5 7
6 8 8 9

Sample Output

14
16
思路:因为(Ai+Aj)(Ai+Aj)=0,所以剩下的只有(A1+A1)(A2+A2)...
所以结果就是每个数两倍的异或

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int maxn=500010;const int maxm=1010;const int MOD=1e9+7;const int INF=0x3f3f3f3f;LL N,M,Z,L;LL a[maxn];int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%I64d%I64d%I64d%I64d",&N,&M,&Z,&L);        a[1]=0;        for(LL i=2; i<=N; i++)            a[i]=(a[i-1]*M+Z)%L;        LL ans=0;        for(LL i=1; i<=N; i++)            ans^=(2*a[i]);        printf("%I64d\n",ans);    }    return 0;}

MZL’s endless loop

Problem Description

As we all kown, MZL hates the endless loop deeply, and he commands you to solve this problem to end the loop.
You are given an undirected graph with n vertexs and m edges. Please direct all the edges so that for every vertex in the graph the inequation |out degree − in degree|≤1 is satisified.
The graph you are given maybe contains self loops or multiple edges.

Input

The first line of the input is a single integer T, indicating the number of testcases.
For each test case, the first line contains two integers n and m.
And the next m lines, each line contains two integers ui and vi, which describe an edge of the graph.
T100,1n105,1m3105,n2105,m7105.

Output

For each test case, if there is no solution, print a single line with −1, otherwise output m lines,.
In ith line contains a integer 1 or 0, 1 for direct the ith edge to ui→vi, 0 for ui←vi.

Sample Input

2
3 3
1 2
2 3
3 1
7 6
1 2
1 3
1 4
1 5
1 6
1 7

Sample Output

1
1
1
0
1
0
1
0
1
官方题解
下面思路转子:hdu5348(2015多校5)–MZL’s endless loop(搜索)
直接进行搜索,对每个点进行出度和入度的判断,如果出度大,就先进行反向的搜索(每搜索一条边u,v就认为这是一条v到u的有向边),反之,进行正向搜索(每搜到一条边u,v认为这是一条u到v的有向边),一直搜索到找不到边能继续为止。

注意:

1、已经使用过的边为了防止再次被遍历,可以修改head,head[u] = edge[i].next

2、注意自环,因为搜索是判断能不能继续向下搜索时,使用了v的入度和出度比较,那么如果是自环可能会被判断不能被加上。

证明不会有-1的情况,对于一个点v,假设入度比出度多2,那么,第一:就会有一条边搜索到v后找不到后继,导致v的入度比出度多1,第二:又有一条边搜索到v,导致v的入度比出度多2,但是这样的话就会和第一条找不到后继冲突,所以不会出现入度比出度多2的情况,(其他情况也是类似),所以不会有-1的结果。

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int maxn=500010;const int maxm=1010;const int MOD=1e9+7;const int INF=0x3f3f3f3f;int N,M,tot;int in[maxn],out[maxn],cnt[maxn];int head[maxn],ans[700010*2],vis[700010*2];struct Node{    int v,next,id;}edge[700010*2];void add_edge(int u,int v,int id){    edge[tot].v=v;    edge[tot].next=head[u];    edge[tot].id=id;    head[u]=tot++;}void dfs1(int u){    for(int i=head[u];i!=-1;i=edge[i].next)    {        if(vis[i])        {            head[u]=edge[i].next;            continue;        }        int v=edge[i].v;        if(u!=v&&in[v]>out[v])continue;        vis[i]=vis[i^1]=1;        if(i%2)ans[i/2]=0;        else ans[i/2]=1;        out[u]++,in[v]++;        head[u]=edge[i].next;        dfs1(v);        break;    }}void dfs2(int u){    for(int i=head[u];i!=-1;i=edge[i].next)    {        if(vis[i])        {            head[u]=edge[i].next;            continue;        }        int v=edge[i].v;        if(u!=v&&in[v]<out[v])continue;        vis[i]=vis[i^1]=1;        if(i%2)ans[i/2]=1;        else ans[i/2]=0;        out[v]++,in[u]++;        head[u]=edge[i].next;        dfs2(v);        break;    }}int main(){    int T,u,v;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&N,&M);        tot=0;        for(int i=1;i<=N;i++)        {            head[i]=-1;            in[i]=out[i]=cnt[i]=0;        }        for(int i=0;i<=2*M;i++)            vis[i]=0;        for(int i=0;i<M;i++)        {            scanf("%d%d",&u,&v);            add_edge(u,v,i);            add_edge(v,u,i);            cnt[u]++,cnt[v]++;        }        for(int i=1;i<=N;i++)        {            while(in[i]+out[i]<cnt[i])            {                if(in[i]>=out[i])dfs1(i);                else dfs2(i);            }        }        for(int i=0;i<M;i++)            printf("%d\n",ans[i]);    }    return 0;}

MZL’s Border

Problem Description

As is known to all, MZL is an extraordinarily lovely girl. One day, MZL was playing with her favorite data structure, strings.

MZL is really like Fibonacci Sequence, so she defines Fibonacci Strings in the similar way. The definition of Fibonacci Strings is given below.

1) fib1=b

2) fib2=a

3) fibi=fibi−1fibi−2, i>2

For instance, fib3=ab, fib4=aba, fib5=abaab.

Assume that a string s whose length is n is s1s2s3…sn. Then sisi+1si+2si+3…sj is called as a substring of s, which is written as s[i:j].

Assume that in. If s[1:i]=s[n−i+1:n], then s[1:i] is called as a Border of s. In Borders of s, the longest Border is called as s’ LBorder. Moreover, s[1:i]’s LBorder is called as LBorderi.

Now you are given 2 numbers n and m. MZL wonders what LBorderm of fibn is. For the number can be very big, you should just output the number modulo 258280327(=2×317+1).

Note that 1T100,1n103,1m|fibn|.

Input

The first line of the input is a number T, which means the number of test cases.

Then for the following T lines, each has two positive integers n and m, whose meanings are described in the description.

Output

The output consists of T lines. Each has one number, meaning fibn’s LBorderm modulo 258280327(=2×317+1).

Sample Input

2
4 3
5 5

Sample Output

1
2
这里写图片描述

import java.math.BigInteger;import java.util.Scanner;public class Main {    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        int T;        int MOD=258280327;        BigInteger f[]=new BigInteger[1010];        f[0]=BigInteger.ZERO;        f[1]=f[2]=BigInteger.ONE;        for(int i=3;i<=1000;i++){            f[i]=f[i-1].add(f[i-2]);        }        Scanner read=new Scanner(System.in);        T=read.nextInt();        int n;        BigInteger m=BigInteger.ZERO;        while(T-->0){            n=read.nextInt();            m=read.nextBigInteger();            if(m.compareTo(BigInteger.ZERO)==0){                System.out.println(1);                continue;            }            if(m.compareTo(BigInteger.valueOf(2))==0){                System.out.println(0);                continue;            }            int x=0;            //System.out.println(m);            for(int i=1;i<=1000;i++){                //System.out.println(m+" "+f[i]);                if(m.compareTo(f[i].subtract(BigInteger.ONE))<0){                    x=i;                    break;                }            }            //System.out.println(x);            System.out.println(m.subtract(f[x-2]).mod(BigInteger.valueOf(MOD)));        }    }}

MZL’s City

Problem Description

MZL is an active girl who has her own country.

Her big country has N cities numbered from 1 to N.She has controled the country for so long and she only remebered that there was a big earthquake M years ago,which made all the roads between the cities destroyed and all the city became broken.She also remebered that exactly one of the following things happened every recent M years:

1.She rebuild some cities that are connected with X directly and indirectly.Notice that if a city was rebuilt that it will never be broken again.

2.There is a bidirectional road between city X and city Y built.

3.There is a earthquake happened and some roads were destroyed.

She forgot the exactly cities that were rebuilt,but she only knew that no more than K cities were rebuilt in one year.Now she only want to know the maximal number of cities that could be rebuilt.At the same time she want you to tell her the smallest lexicographically plan under the best answer.Notice that 8 2 1 is smaller than 10 0 1.

Input

The first contains one integer T(T<=50),indicating the number of tests.

For each test,the first line contains three integers N,M,K(N<=200,M<=500,K<=200),indicating the number of MZL’s country ,the years happened a big earthquake and the limit of the rebuild.Next M lines,each line contains a operation,and the format is “1 x” , “2 x y”,or a operation of type 3.

If it’s type 3,first it is a interger p,indicating the number of the destoyed roads,next 2*p numbers,describing the p destoyed roads as (x,y).It’s guaranteed in any time there is no more than 1 road between every two cities and the road destoyed must exist in that time.

Output

The First line Ans is the maximal number of the city rebuilt,the second line is a array of length of tot describing the plan you give(tot is the number of the operation of type 1).

Sample Input

1
5 6 2
2 1 2
2 1 3
1 1
1 2
3 1 1 2
1 2

Sample Output

3
0 2 1
Hint
No city was rebuilt in the third year,city 1 and city 3 were rebuilt in the fourth year,and city 2 was rebuilt in the sixth year.
思路:对于每一个1操作,我们将1操作当做一个点,并拆成k个点,然后每个点和x的连通块内的所以点连边。
对于每一个2操作,暴力加边。
对于每一个3操作,暴力删边。

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int maxn=7010;const int maxm=100010;const int MOD=1e9+7;const int INF=0x3f3f3f3f;int N,M,K,E,ST,EN,cas;int vis[maxn][maxn];int pre[maxn];int path[maxn][maxn];int X[maxn],Y[maxn];int ans[maxn];int tot,num;int head[maxn];int nn;int cur[maxn],dis[maxn],gap[maxn];void init(){    E=tot=num=0;    memset(head,-1,sizeof(head));}struct node{    int v,next,f;}edge[maxm*2];void add_edge(int x,int y,int f){    edge[num].v=y;    edge[num].f=f;    edge[num].next=head[x];    head[x]=num++;    edge[num].v=x;    edge[num].f=0;    edge[num].next=head[y];    head[y]=num++;}int SAP(int st,int en){    for(int i=0;i<=nn;i++)    {        cur[i]=head[i];        dis[i]=gap[i]=0;    }    int u=0;    int flow=0,aug=INF;    gap[st]=nn;    u=pre[st]=st;    bool flag;    while(dis[st]<nn)    {        flag=0;        for(int &j=cur[u];j!=-1;j=edge[j].next)        {            int v=edge[j].v;            if(edge[j].f>0&&dis[u]==dis[v]+1)            {                flag=1;                if(edge[j].f<aug)aug=edge[j].f;                pre[v]=u;                u=v;                if(u==en)                {                    flow+=aug;                    while(u!=st)                    {                        u=pre[u];                        edge[cur[u]].f-=aug;                        edge[cur[u]^1].f+=aug;                    }                    aug=INF;                }                break;            }        }        if(flag)continue;        int mindis=nn;        for(int j=head[u];j!=-1;j=edge[j].next)        {            int v=edge[j].v;            if(dis[v]<mindis&&edge[j].f>0)            {                mindis=dis[v];                cur[u]=j;            }        }        if((--gap[dis[u]])==0)break;        gap[dis[u]=mindis+1]++;        u=pre[u];    }    return flow;}int find(int x){    if(pre[x]==x)return x;    return pre[x]=find(pre[x]);}void solve(int id,int x){    for(int i=0;i<=N;i++)pre[i]=i;    for(int i=1;i<=E;i++)        if(vis[X[i]][Y[i]]==cas)pre[find(X[i])]=find(Y[i]);    find(x);    path[id][0]=cas;    for(int i=1;i<=N;i++)        path[id][i]=(pre[x]==find(i))*cas;}int main(){    int T;    scanf("%d",&T);    for(cas=1;cas<=T;cas++)    {        int p,x,y,op;        init();        scanf("%d%d%d",&N,&M,&K);        for(int i=1;i<=M;i++)        {            scanf("%d",&op);            if(op==1)            {                scanf("%d",&x);                solve(i,x);            }            else if(op==2)            {                ++E;                scanf("%d%d",&X[E],&Y[E]);                if(X[E]>Y[E])swap(X[E],Y[E]);                vis[X[E]][Y[E]]=cas;            }            else            {                scanf("%d",&p);                for(int i=0;i<p;i++)                {                    scanf("%d%d",&x,&y);                    if(x>y)swap(x,y);                    vis[x][y]=0;                }            }        }        int sum=0;        ST=N+1,EN=tot=ST+1;        for(int i=1;i<=N;i++)add_edge(i,EN,1);        int cnt=0;        for(int i=M;i>=1;i--)        {            if(path[i][0]==cas)            {                add_edge(ST,++tot,K);                for(int j=1;j<=N;j++)                    if(path[i][j]==cas)                        add_edge(tot,j,1);                nn=tot+1;                int tmp=SAP(ST,EN);                ans[cnt++]=tmp;                sum+=tmp;            }        }        printf("%d\n",sum);        for(int i=cnt-1;i>=0;i--)        {            printf("%d",ans[i]);            if(i==0)printf("\n");            else printf(" ");        }    }    return 0;}

MZL’s munhaff function
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 167 Accepted Submission(s): 104

Problem Description
MZL is a mysterious mathematician, and he proposed a mysterious function at his young age.
Stilwell is very confused about this function, and he need your help.
First of all, given n positive integers Ai and Ai≥Ai+1.
Then, generate n positive integers Bi
Bi=nj=iAj

Define f(i,j) for i,j∈Z

f(i,j)=\left\ {

0min(f(i1,j+1),f(i,j2)+Bi)1011037(i,j)=(1,1)i,j[1,n], (i,j)(1,1)otherwise
\right.
Find f(n,1).

Input
The first line of the input contains a single number T, the number of test cases.
For each test case, the first line contains a positive integer n, and the next line contains n positive integers Ai.
T≤100, 1≤n≤105, ∑n≤106, 1≤Ai≤104.

Output
For each test case, output f(n,1) in a line.

Sample Input

3
3
1 1 1
5
28 26 25 24 1
10
996 901 413 331 259 241 226 209 139 49

Sample Output

5
233
11037
Hint

case 1 :
f(1,1)=0
f(1,2)=f(1,1)+3=3
f(1,3)=f(1,2)+3=6
f(2,1)=min(f(2,1)+2,f(1,2))=3
f(2,2)=min(f(2,1)+2,f(1,3))=5
f(2,3)=f(2,2)+2=7
f(3,1)=min(f(3,1)+1,f(2,2))=5

看到题解之后深深地折服了。。。
这里写图片描述
表示两种决策,第一种对于Ai作为一个叶子节点,下一个处理Ai+1,或者不处理Ai,而是扩展节点成两倍,下次处理Ai,那么可以看出这就是一个哈弗曼模型,简直厉害

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int maxn=100010;const int maxm=1010;const int MOD=1e9+7;const int INF=0x3f3f3f3f;int N,a[maxn];int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&N);        for(int i=1;i<=N;i++)scanf("%d",&a[i]);        LL ans=0;        priority_queue<LL,vector<LL>,greater<LL> > q;        for(int i=1;i<=N;i++)q.push(a[i]);        while(q.size()>=2)        {            LL a=q.top();q.pop();            LL b=q.top();q.pop();            ans+=a+b;            q.push(a+b);        }        printf("%I64d\n",ans);    }    return 0;}
0 0
原创粉丝点击