• 2014-10-24 NOIP欢乐赛


     

     

    10-24NOIP欢乐赛

    ——By 潘智力

     

    题目名称

    分火腿

    无聊的会议

    班服

    时间限制

    1s

    1s

    1s

    内存限制

    64MB

    128MB

    128MB

    输入文件

    hdogs.in

    meeting.in

    shirt.in

    输出文件

    hdogs.out

    meeting.out

    shirt.out

    测试点个数

    10

    10

    10

     

     

     

    测评环境:windows系统

    水题,众神轻虐

     

     

     

     

     

     

    分火腿

    (hdogs.pas/.c/.cpp)

    时间限制:1s;内存限制 64MB

    题目描述:

    小月言要过四岁生日了,她的妈妈为她准备了n根火腿,她想将这些火腿均分给m位小朋友,所以她可能需要切火腿。为了省事,小月言想切最少的刀数,使这n根火腿分成均等的m份。请问最少要切几刀?

    输入描述:

    第一行一个整数T,表示有T组数据。

    接下来T组数据,每组共一行,有两个数字n,m。

    输出描述:

    每组数据一行,输出最少要切的刀数。

    样例输入:

    2

    2 6

    6 2

    样例输出:

    4

    0

    数据范围:

    100%的数据保证T<=1000;n,m<=2147483647。

    /*
        题目相当于一根长为n的火腿肠,切成m段,如果从整数部分切开则不需要代价,否则代价1
        n根火腿切m份,每一份长n/m,我们发现对于 n/m * K 为整数的情况,就不用刀子切
        k共有n/lcm(n/m,1)-1=gcd(n,m)-1个,所以最终要切m-gcd(n,m)次
    */
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,T;
    int gcd(int x,int y){
        if(y==0)return x;
        return gcd(y,x%y);
    }
    int main(){
        freopen("hdogs.in","r",stdin);
        freopen("hdogs.out","w",stdout);
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            printf("%d
    ",m-gcd(n,m));
        }
    }
    100分 数学推理

     

    无聊的会议

    (meeting.pas/.c/.cpp)

    时间限制:1s;内存限制 128MB

    题目描述:

    土豪学长作为一名光荣的学生会干部,每天要参加很多无聊的会议。他发现:他开会的会议桌一定是正n边形,n个干部坐在这个多边形顶点上。因为太无聊了,所以他想要数出所有的“完全”等腰三角形——这种等腰三角形的三个顶点一定全是给出n多边形的顶点,且三个顶点上坐的干部性别相同。

    土豪学长是土豪,他用1000000000%10的佣金雇用你,让你帮他数。PS:如果两个“完全”等腰三角形三个顶点相同,计算时只算一个。

    输入描述:

    第一行一个数字T,表示有T组数据。

    接下来有T组数据,每组数据共一行。这一行给出一个长度为n的字符串,表示正n边形n个顶点上干部的性别。1为男,0为女。

    输出描述:

    对于第i组数据:输出”Case i: ans”(不带引号),ans为“完全”等腰三角形的数量。

    样例输入:

    5

    0001

    01

    10001

    1101010

    111010

    样例输出:

    Case 1: 1

    Case 2: 0

    Case 3: 1

    Case 4: 3

    Case 5: 2

    数据范围:

    40%的数据保证n<=20

    100%的数据保证 n<=10^6

    所有数据保证T<=10

    /*
        法一:可以假设男性为黑点,女性为白点。枚举一个等腰三角形的顶点,再枚举一个底边点。这个三角形就确定下来了。求同色三角形的个数。n2做法。
        法二:所有等腰三角形的个数-所有异色等腰三角形的个数=所有同色三角形的个数。
            枚举顶点,然后在枚举任一与他颜色不同的底边点(即为多边形上所有与它颜色不同的点的个数O(1)),求出异色边的数量。这样子有一种三角形(顶点与两底边点一个为同色,一个为异色)数了一次,有一种三角形(顶点与两底边点均为异色)数了两次。可以使其都计算两次。
            计算顶点与一底边点一个为同色,一个为异色的三角行的个数:枚举两个底端点,保证其颜色不一样。n为奇数时,任意两个点都能形成底边。n为偶数时,奇偶性相同的点能形成底边。异色边都计算了两次,除以2,就是底边异色的个数。即为三角形的个数。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define ll long long
    int T,n;
    char a[1000005];
    
    ll calcu(){
        ll ans=0;
        ans=(ll)n*((n-1)/2);
        if(n%3==0)ans-=n/3*2;
        return ans;
    }
    ll del(){
        ll ans;
        if(n%2==1){
            int s1=0,i,s0=0;
            for(i=0;i<n;i++){
                if(a[i]=='0')s0++;
                else s1++;
            }
            ans=(ll)s1*s0*3;
            if(n%3==0){
                s1=n/3;s0=n/3*2;
                for(i=0;i<n;i++){
                    if(a[i]!=a[(i+s1)%n])ans--;
                    if(a[i]!=a[(i+s0)%n])ans--;
                }
            }
            return ans/2;
        }
        else {
            int i,s00=0,s01=0,s10=0,s11=0;
            for(i=0;i<n;i+=2){
                if(a[i]=='0')s00++;
                else s01++;
            }
            for(i=1;i<n;i+=2){
                if(a[i]=='0')s10++;
                else s11++;
            }
            ans=(ll)s00*s11*2;ans+=(ll)s01*s10*2;
            ans+=(ll)s00*s01*4;ans+=(ll)s10*s11*4;
            int n1,n2;
            n1=n/2;
            for(i=0;i<n;i++)
                if(a[i]!=a[(i+n1)%n])ans--;
            if(n%3==0){
                int s1=n/3,s0=n/3*2;
                for(i=0;i<n;i++){
                    if(a[i]!=a[(i+s1)%n])ans--;
                    if(a[i]!=a[(i+s0)%n])ans--;
                }
            }
            return ans/2;
        }
    }
    int main(){
        freopen("meeting.in","r",stdin);
        freopen("meeting.out","w",stdout);
        scanf("%d",&T);
        int Case=0;
        while(T--){
            Case++;
            scanf("%s",&a);
            n=strlen(a);
            printf("Case %d: %I64d
    ",Case,calcu()-del());
        }
        return 0;
    }
    100分

    班服

     (shirt.pas/.c/.cpp)

    时间限制:1s;内存限制 128MB

    题目描述:

    要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100。现在每个班都挑出了一些样式待选,每个班最多有100个待选的样式。要求每个班最终选定一种样式作为班服,且该班的样式不能与其他班级的相同,求所有可能方案的总数,由于方案总数可能很大,所以要求输出mod 1000000007后的答案。

    输入描述:

    共有T组数据。

    对于每组数据,第一行为一个整数n,表示有n个班级。

    2~n+1行,每行有最多100个数字,表示第i-1班待选班服的编号。

    输出描述:

    对于每组数据,输出方案总数 mod 1000000007后的答案。

    样例输入:

    2

    3

    5 100 1

    2

    5 100

    2

    3 5

    8 100

    样例输出:

    4

    4

    数据范围:

    对于30%的数据,1<=T<=3, 1<=n<=3,每班待选样式不超过10种。

    对于50%的数据,1<=T<=5, 1<=n<=5,每班待选样式不超过50种。

    对于100%的数据,1<=T<=10, 1<=n<=10,每班待选样式不超过100种。

    /*
        把班级状压一下
        f[i][j]表示前i件衣服达到j状态的方案
        那么显然f[i][j]+=f[i-1][j]
        若班级k可以穿i这件衣服,则f[i][j]+=f[i-1][j-(1<<(k-1))]
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 1000000007
    using namespace std;
    int T,n,bin[11],a[11][110],f[110][1025];
    bool flag;
    int qread(){
        int i=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
        if(ch=='
    ')flag=1;
        return i;
    }
    int main(){
        freopen("shirt.in","r",stdin);
        freopen("shirt.out","w",stdout);
        scanf("%d",&T);
        for(int i=0;i<=10;i++)bin[i]=1<<i;
        while(T--){
            memset(a,0,sizeof(a));
            memset(f,0,sizeof(f));
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                flag=0;
                while(1){
                    int s=qread();
                    a[i][s]=1;
                    if(flag==1)break;
                }
            }
            f[0][0]=1;
            int tot=(1<<n)-1;
            for(int i=1;i<=100;i++){
                for(int j=0;j<=tot;j++){
                    f[i][j]=f[i-1][j];
                    for(int k=1;k<=n;k++)
                        if(a[k][i]&&(j&(1<<k-1)))
                            f[i][j]=(f[i][j]+f[i-1][j^(1<<k-1)])%mod;
                }
            }
            printf("%d
    ",f[100][tot]);
        }
    }
    100分 状压dp
  • 相关阅读:
    Chapter 03Using SingleRow Functions to Customize Output(03)
    Chapter 03Using SingleRow Functions to Customize Output(01)
    Chapter 04Using Conversion Functions and Conditional ExpressionsNesting Functions
    Chapter 04Using Conversion Functions and Conditional ExpressionsGeneral Functions
    Chapter 11Creating Other Schema Objects Index
    传奇程序员John Carmack 访谈实录 (zz.is2120)
    保持简单纪念丹尼斯里奇(Dennis Ritchie) (zz.is2120.BG57IV3)
    王江民:传奇一生 (zz.is2120)
    2011台湾游日月潭
    2011台湾游星云大师的佛光寺
  • 原文地址:https://www.cnblogs.com/thmyl/p/7490629.html
Copyright © 2020-2023  润新知