• NOIP1998提高组 题解报告


    T1 进制位

    题目大意:自己看吧

    首先让我们来看两个引理:

    • 如果有解,则进制一定为(n - 1)
    • 如果有解,则字母一定表示(0)(n - 1) 的数

    证明如下:

    因为有 (n - 1) 个不同的数,所以最少 (n - 1) 进制。

    假设为 (n) 进制,那么一定有一个数没有出现,假设为 (k)

    1. (k = 0)(k = 1),有 (1 + (n - 1) = 10)(n)进制下) ,矛盾。

    2. (1 < k le n-1) ,有(1 + (k - 1) = k) ,矛盾。

    其它 $ > n - 1$ 进制的情况同理,所以一定是 (n - 1) 进制,结论 (1) 得证。

    结论 (1) 成立 ,则结论 (2) 显然。

    有了以上两个结论,这道题就好做多了。

    数据范围才为 (n le 9) ,直接枚举每种全排列,对每一种进行判断是否满足加法表就行了。

    (Code:)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int n,a[9],c[366666][9],tot,num[233],vis[233];
    char cnm[9];
    char ch[9][9][233];
    inline int my_pow(int a,int b)
    {
        int cnm=1;
        for(;b;b>>=1)
        {
            if(b&1) cnm=cnm*a;
            a=a*a;
        }
        return cnm;
    }
    inline bool calc(int jz,int a,int b)
    {
        int A=num[(int)cnm[a]],B=num[(int)cnm[b]],C=0;
        int siz=ch[a+1][b+1][0];
        for(int i=1;i<=siz;++i)
            C+=num[(int)ch[a+1][b+1][i]]*my_pow(jz,siz-i);
        if(A+B<jz)
        {
            if(A+B==C) return true;
            return false;
        }
        else
        {
            int temp=A+B;
            B=temp%jz,A=temp/jz;
            B+=A*jz;
            if(B==C) return true;
            return false;
        }
    }
    inline void dfs(int k)
    {
        if(k==n-1)
        {
            ++tot;
            for(int i=0;i<n-1;++i) c[tot][i]=a[i];
            return;
        }
        for(int i=0;i<n-1;++i)
        {
            if(!vis[i])
            {
                vis[i]=1;
                a[k]=i,dfs(k+1);
                vis[i]=0;
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        getchar();//小心换行
        for(int i=0;i<n;++i)
        {
            for(int j=0;j<n;++j)
            {
                scanf("%s",ch[i][j]+1);
                ch[i][j][0]=strlen(ch[i][j]+1);
            }
        }
        for(int i=1;i<n;++i) cnm[i-1]=ch[0][i][1];
        dfs(0);
        for(int i=1;i<=tot;++i)
        {
            int sum=0;
            for(int j=0;j<n-1;++j) num[(int)cnm[j]]=c[i][j];
            for(int j=0;j<n-1;++j)
            {
                for(int k=0;k<n-1;++k)
                {
                    if(calc(n-1,j,k)) ++sum;
                }
            }
            if(sum==(n-1)*(n-1))
            {
                for(int j=0;j<n-1;++j) printf("%c=%d ",cnm[j],c[i][j]);
                puts("");
                printf("%d
    ",n-1);return 0;
            }
        }
        puts("ERROR!");
        return 0;
    }
    
    

    T2 拼数

    题目大意:给你(n)个正整数,让你把它们重新排列,使得排列后形成的数最大。

    水题,直接(STL)切掉

    (Code:)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<iostream>
    using namespace std;
    int n;
    string s[23];
    inline bool cmp(string a,string b) {return a+b>b+a;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) cin>>s[i];
        sort(s+1,s+n+1,cmp);
        for(int i=1;i<=n;++i) cout<<s[i];
        return 0;
    }
    
    

    T3 车站

    题目大意:给你列车每一站上下车人数的规律以及终点人数,求第(x)站人数。

    水的不能再水的题,直接上代码……

    (Code:)

    #include<cstdio>
    using namespace std;
    int f[23],n,m,a,x;
    int main()
    {
        scanf("%d%d%d%d",&a,&n,&m,&x);
        f[1]=1,f[2]=1;
        for(int i=3;i<=n;++i) f[i]=f[i-1]+f[i-2];
        if(x==1 || x==2) printf("%d",a);
        else if(x==3) printf("%d",2*a);
        else
        {
            int y=(m-a*(f[n-3]+1))/(f[n-2]-1);
            printf("%d",y*(f[x-1]-1)+a*(f[x-2]+1));
        }
        return 0;
    }
    
    
  • 相关阅读:
    flash编程实例源代码下载
    js4:with,for in语句,windows,location对象的使用
    js3:数据类型,数组,String各个属性,以及字符串表达式用eval计算
    挺喜欢这个网站的
    C#Url传递中文参数时解决方法
    .NET设计模式系列文章《转》
    maven surefire plugin介绍
    spring-boot-maven-plugin 插件的作用
    github提交表情包
    接口管理工具
  • 原文地址:https://www.cnblogs.com/p-z-y/p/11720365.html
Copyright © 2020-2023  润新知