2013 Multi-University Training Contest 6

来源:互联网 发布:建筑学概论知乎 编辑:程序博客网 时间:2024/05/16 08:53

1001 Cut Pieces

我们没过的版刷题,可是看了标程后发现我们确实不会,而且最多的排布方式只限于一大一小,我们一开始YY的大的放中间,小的放两边根本是错误的,小数据可能还没什么错,大数据就会发现错误。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<map>#define N 1000000007using namespace std;inline void RD(int &ret){    char c;    do    {        c=getchar();    }    while(c<'0'||c>'9');    ret=c-'0';    while((c=getchar())>='0'&&c<='9')    {        ret=ret*10+(c-'0');    }}inline void OT(int a){    if(a>=10)    {        OT(a/10);    }    putchar(a%10+'0');}long long a[1000001],b[1000001],p[1000001],q[1000001];int main(){    int n,i,t,j,l,r,m;    long long sum,ans;    RD(t);    while(t--)    {        scanf("%d",&n);        for(i=0;i<n;++i)        {            scanf("%I64d",&a[i]);        }        sort(a,a+n);        reverse(a,a+n);//从大到小排列        j=0;        for(i=1;i<n;i+=2)//将a的值一大一小开始赋值到b中        {            b[i]=a[j++];        }        //j=0;        for(i=0;i<n;i+=2)        {            b[i]=a[j++];        }        p[0]=q[n]=1;        for(i=0;i<n;++i)        {            p[i+1]=p[i]*b[i]%N;//构造数列从前乘到后的数        }        for(i=n;i>0;--i)        {            q[i-1]=q[i]*b[i-1]%N;//构造数列从后乘到前的数        }        sum=0;        for(i=0;i<n-1;++i)        {            l=i;            r=i+1;            if(b[l]>b[r])            {                m=l;            }            else            {                m=r;            }            sum=(sum+p[m]*q[m+1])%N;//标程上的方法,只去掉bm        }        ans=n*p[n]%N;        ans=(ans-sum+N)%N;//总数减去重复的        printf("%I64d\n",ans);    }    return 0;}

1004 Integer Partition

这题是之前第五场Partition的扩展,当时只是了解了五角数定理,但没有深入探究,结果这题就是对原先的P(n)在做一次递推运算,只是每次加上或者减去的项为p(n-j*(3*j+-1)*k/2)。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>#define N 1000000007using namespace std;inline void RD(int &ret){    char c;    do    {        c=getchar();    }    while(c<'0'||c>'9');    ret=c-'0';    while((c=getchar())>='0'&&c<='9')    {        ret=ret*10+(c-'0');    }}inline void OT(int a){    if(a>=10)    {        OT(a/10);    }    putchar(a%10+'0');}long long a[100005];void f()//递推式{    int i,j;    long long sum;    a[0]=1;    a[1]=1;    a[2]=2;    for(i=2; i<=100000; ++i)    {        sum=0;        for(j=1; (i-j*(3*j-1)/2)>=0||(i-j*(3*j+1)/2)>=0; j++)        {            if(j%2==1)            {                if((i-j*(3*j-1)/2)>=0)                {                    sum=(sum+a[(i-j*(3*j-1)/2)])%N;//注意不能写+=,不然会产生溢出错误,(不管你是longlong还是int)                }                if((i-j*(3*j+1)/2)>=0)                {                    sum=(sum+a[(i-j*(3*j+1)/2)])%N;                }            }            else            {                if((i-j*(3*j-1)/2)>=0)                {                    sum=(sum-a[(i-j*(3*j-1)/2)]+N)%N;//防止负数                }                if((i-j*(3*j+1)/2)>=0)                {                    sum=(sum-a[(i-j*(3*j+1)/2)]+N)%N;                }            }        }        a[i]=sum;    }}int main(){    f();    int t,n,j,k;    long long sum;    RD(t);    while(t--)    {        scanf("%d%d",&n,&k);        sum=a[n]%N;        for(j=1; (n-j*(3*j-1)*k/2)>=0||(n-j*(3*j+1)*k/2)>=0; j++)//看过才知道只要乘就行,太悲剧了        {            if(j%2==0)            {                if((n-j*(3*j-1)*k/2)>=0)                {                    sum=(sum+a[(n-j*(3*j-1)*k/2)])%N;                }                if((n-j*(3*j+1)*k/2)>=0)                {                    sum=(sum+a[(n-j*(3*j+1)*k/2)])%N;                }            }            else            {                if((n-j*(3*j-1)*k/2)>=0)                {                    sum=(sum-a[(n-j*(3*j-1)*k/2)]+N)%N;                }                if((n-j*(3*j+1)*k/2)>=0)                {                    sum=(sum-a[(n-j*(3*j+1)*k/2)]+N)%N;                }            }        }        printf("%I64d\n",sum%N);    }    return 0;}

1008 MU Puzzle

全场唯一出的水题。

由于三种操作的存在,2^n-6k=sum(‘I的总数(可由U转换成)’),所以当sum=1或sum%6=2或者4时都是可行的

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;inline void RD(int &ret){    char c;    do    {        c=getchar();    }    while(c<'0'||c>'9');    ret=c-'0';    while((c=getchar())>='0'&&c<='9')    {        ret=ret*10+(c-'0');    }}inline void OT(int a){    if(a>=10)    {        OT(a/10);    }    putchar(a%10+'0');}int main(){    int t,i,l,f,sum;    char a[1000001];    RD(t);    while(t--)    {        scanf("%s",a);        l=strlen(a);        f=0;        if(a[0]!='M')        {            f=1;        }        sum=0;        for(i=1;i<l;++i)        {            if(a[i]=='I')            {                sum+=1;            }            else if(a[i]=='U')//将U的数量也转化为I的数量            {                sum+=3;            }            else            {                f=1;            }        }        if(sum%6!=2&&sum%6!=4&&sum!=1)        {            f=1;        }        if(f==1)        {            printf("No\n");        }        else        {            printf("Yes\n");        }    }    return 0;}



1010 Triangulation

空间博弈,Dawson’s Kayles 问题,表示完全不知道,百度一下后也发现只有一篇外语论文有提到。

有兴趣的可以去玩一下这个:传送门

标程上打的表也看不懂,最后还是自己写的sg函数,由于标程上说了循环节是34,所以就开了1000的数组。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;inline void RD(int &ret){    char c;    do    {        c=getchar();    }    while(c<'0'||c>'9');    ret=c-'0';    while((c=getchar())>='0'&&c<='9')    {        ret=ret*10+(c-'0');    }}inline void OT(int a){    if(a>=10)    {        OT(a/10);    }    putchar(a%10+'0');}int sg[1005];bool t[1005];void f(){    int i,j;    for(i=2;i<1000;++i)    {        fill(t,t+i-1,false);        for(j=0;j<=i-2;++j)        {            t[sg[j]^sg[i-2-j]]=true;        }        for(j=0;;++j)        {            if(!t[j])            {                sg[i]=j;                break;            }        }    }}int main(){    f();    int t,i,n,x,sum;    RD(t);    while(t--)    {        RD(n);        sum=0;        for(i=0;i<n;++i)        {            RD(x);            if(x<=100)            {                sum^=sg[x];            }            else            {                sum^=sg[x%34+3*34];            }        }        if(sum==0)        {            printf("Dave\n");        }        else        {            printf("Carol\n");        }    }    return 0;}


1011 Unshuffle

最坑的题啊,题意很好理解,还是special judge,但最后也没发现这居然是一道2-sat。。。建完图,最后一个简单的dfs就搞定了。。。无语啊

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;inline void RD(int &ret){    char c;    do    {        c=getchar();    }    while(c<'0'||c>'9');    ret=c-'0';    while((c=getchar())>='0'&&c<='9')    {        ret=ret*10+(c-'0');    }}inline void OT(int a){    if(a>=10)    {        OT(a/10);    }    putchar(a%10+'0');}int a[2001],v[2001],n;bool dfs(int x,int y){    int i,j,f=0;    if(x>=n-2)    {        return 1;    }    for(i=x;i<n-1;++i)    {        if(v[i]==0)        {            v[i]=-1;            for(j=y;j<n;++j)            {                if(a[i]==a[j]&&v[j]==0)                {                    v[j]=1;                    if(dfs(i+1,j+1)==1)                    {                        return 1;                    }                    v[j]=0;                }            }            f=1;            v[i]=0;            break;        }    }    if(f==0)    {        return 1;    }    return 0;}int main(){    int t,i;    RD(t);    while(t--)    {        memset(v,0,sizeof(v));        RD(n);        for(i=0;i<n;++i)        {            RD(a[i]);        }        dfs(0,1);        for(i=0;i<n;++i)        {            if(v[i]==-1)            {               OT(0);            }            else if(v[i]==1)            {                OT(1);            }        }        printf("\n");    }    return 0;}