zoukankan      html  css  js  c++  java
  • 【2018 9th C++】 蓝桥杯决赛

    (1.) 换零钞

    题意

    钞票一共有(100、5、2、1)四种,现在有(2)(100)元的钞票,去换零钱,要换出的零钱中(2)元的是(1)元的(10)倍,剩下的都是(5)元面额的

    数据范围

    题解

    换的钱张数最少,即(1)元的最少,枚举(1)元的数目即可,然后得到(2)元的数目,最后判断一下剩余的金钱数能不能用(5)元的凑出来

    Code

    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    int main()
    {
        int one=0;
        int res=0;
        for(int i=1;i<=200;i++)
        {
            if((200-i*2*10-i)%5==0)
            {
                one=i;
                res=200-(i*2*10+i);
                break;
            }    
        }
        int ans;
        ans=one+10*one;
        ans=ans+res/5;
        printf("%d
    ",ans);
    }
    

    (2.) 激光样式

    题意

    (30)个灯,相邻的两个不能够同时亮,问一共能够有多少种不同的打开方式,全部关闭也算是一种

    数据范围

    (1leq nleq 30)

    题解

    暴力搜索所有可能的状态,全为(0)也算是一种

    Code

    #include<iostream>
    using namespace std;
    bool st[35];
    int ans=0;
    void dfs(int u,int pre){
        if(u==31){
            ans++;
            return;
        }
        if(pre==0){
            dfs(u+1,1);
        }
        dfs(u+1,0);
    }
    int main(){
        dfs(1,0);
        cout<<ans<<endl;
    }
    

    (3.) 格雷码

    题意

    代码填空,实现对一个数(x)求出其二进制下最右边的一个(1),并将其左边的二进制数字进行改变

    数据范围

    题解

    (lowbit)操作能求出最右边的1,低位补(0)后的数字,将其左移一位置,即在后面加一个(0),求得的数字即当前最右边的(1)左边数字对应的数字为(1)的值,将原值与其异或后就可以求得改变后的数字

    Code

    x ^ (x&(-x)<<1)
    

    (4.) 调手表

    题意

    给定(n)进制的手表,和一个(k),在任意时刻,有两个操作可以进行,(+1)或者(+k),手表只能显示(0sim n-1)的数字,
    在最优策略下,求出从任意时间到达其他任意时间的操作数的最大值

    数据范围

    (0< k < n < 100000)

    题解

    因为是(mod)循环,可以看做是从(1)(n-1)的所有最优方案,最小步数模型,(bfs)即可,所有步数的最大值即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    const int N=1e5+10;
    int n,k;
    int ans;
    int dist[N];
    void bfs(){
        memset(dist,-1,sizeof dist);
        queue< int > q;
        q.push(0);
        dist[0]=0;
        while(q.size()){
            int t=q.front();
            q.pop();
    
            int tx=(t+1)%n,ty=(t+k)%n;
    
            if(dist[tx]==-1){
                dist[tx]=dist[t]+1;
                ans=max(ans,dist[tx]);
                q.push(tx);
            }
            if(dist[ty]==-1){
                dist[ty]=dist[t]+1;
                ans=max(ans,dist[ty]);
                q.push(ty);
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&k);
        bfs();
        cout<<ans<<endl;
    }
    

    (5.) 搭积木

    题意

    输入一个(n,m),之后输入(n)行,每行(m)个字符表示当前是否可以放置,如果为(.)则可以放置,如果为(X)则不能放置,积木的放置必须满足以下三个规则,

    • 当前可以防止积木当且仅当当前位置上一行放置了积木

    • 每一行中积木的放置必须是连续的

    默认第(0)行已经全部放置,求有多少种可能的放置方案,答案(mod; 10^{9}+7)

    数据范围

    (1leq n,mleq 10^{5})

    题解

    • 状态表示: (dp[i][l][r])在第(i)层的(lsim r)区间都放上积木的方案数

      • (lsim r)中能放上积木当且仅当(i-1)层中(lsim r)都已经放上了积木,否则就为(0)

      • 当前行相同的放置,之前的行只要有不同的放置就算是不同的方案

    • 状态转移:(dp[i][l][r] = sum_{j=1}^{l} sum_{k=r}^{m} dp[i-1][j][k])

      • 当前的状态计算中不包含都不放的方案,所以答案的初始值需要设置为(1)

    Code

    #include<iostream>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define ll long long
    const int mod=1000000007,N=110;
    
    char g[N][N];
    ll s[N][N],dp[N][N][N];
    int c[N][N];
    int n,m;
    int ans;
    
    void add_suffix(int i){
        rep(j,1,m) rep(k,1,m){
            s[j][k]=s[j-1][k]+s[j][k-1]-s[j-1][k-1]+dp[i][j][k];
        }
    }
    ll get_suffix(int x1,int y1,int x2,int y2){
        return (s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])%mod;
    }
    int main(){
        cin>>n>>m;
        per(i,n,1) scanf("%s",g[i]+1);
        rep(i,1,n)
            rep(j,1,m)
                c[i][j]=c[i][j-1]+(g[i][j]=='X');
    
        dp[0][1][m]=1;
        add_suffix(0);
        int res=1;
        rep(i,1,n){
            rep(j,1,m){
                rep(k,j,m){
                    if(c[i][k]-c[i][j-1]==0){
                        ll &x=dp[i][j][k];
                        x=(x+get_suffix(1,k,j,m))%mod;
                        res=(res+x)%mod;
                    }
                }
            }
            add_suffix(i);
        }
    
        // rep(i,1,n){
        //     rep(j,1,m){
        //         cout<<dp[i][j]<<' ';
        //     }
        //     cout<<endl;
        // }
        cout<<(res+mod)%mod<<endl;
    }
    
    

    (6.) 矩阵求和

    题意

    给定一个(n),矩阵的每个位置((i,j))元素值等于(gcd(i,j)),求(n imes n)的矩阵的元素值之和

    数据范围

    (1leq nleq 10^{7})

    题解

    最大公约数(d)的范围为(1leq n)

    • 对于(i,j in [d,n],gcd(i,j)=d)的个数

    • (i,jin [1,lfloor frac{n}{d} floor],gcd(i,j)=1)的数对的个数是一一对应的

    • 满足(i<j),且(gcd(i,j)=1)的数对个数即(sum_{x=2}^{j} phi(x) + 1)

    • (i>j)时候个数上同(i<j)一样,二者都包含了((1,1))容斥掉即可

    对于(iin [1,i-1])中与其互质的数的个数即欧拉函数(phi (i))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    const int N=1e7+10,mod=1e9+7;
    
    
    ll phi[N];
    ll s[N];
    bool st[N];
    int primes[N],cnt;
    void get_eulers(int n){
        phi[1]=1;
        for (int i = 2; i <=n ; ++i) {
            if(!st[i]) {
                primes[cnt++]=i;
                phi[i]=i-1;
            }
            for (int j = 0; primes[j] <=n/i ; ++j) {
                st[primes[j]*i]=true;
                if(i%primes[j]==0) {
                    phi[primes[j]*i]=primes[j]*phi[i];
                    break;
                }
                phi[primes[j]*i]=phi[i]*(primes[j]-1);
            }
        }
    
        s[1]=phi[1];
        rep(i,2,n) s[i]=(s[i-1]+phi[i]*2)%mod;
    }
    // void get_eulers(int n){
    //     rep(i,2,n) phi[i]=0;
    //     phi[1]=1;
    //     for(int i=2;i<=n;i++){
    //         if(!phi[i]){
    //             for(int j=i;j<=n;j+=i){
    //                 if(!phi[j]) phi[j]=j;
    //                 phi[j]=phi[j]/i*(i-1);
    //             }
    //         }
    //     }
    //     s[1]=phi[1];
    //     rep(i,2,n) s[i]=(s[i-1]+phi[i]*2)%mod;
    // }
    int main(){
        int n;
        cin>>n;
        get_eulers(n);
        ll ans=0;
        rep(d,1,n) ans=(ans+s[n/d]*d%mod*d)%mod;
        cout<<ans<<endl;
    }   
    
  • 相关阅读:
    关于通胀,交易手续费和加密货币的货币政策
    私有链和联盟链的机会与挑战
    耶鲁大学公开课:博弈论第九节(笔记)
    区块链匿名技术
    区块链对比数据库
    硬盘 分区 格式化 和挂载
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
  • 原文地址:https://www.cnblogs.com/hhyx/p/13873358.html
Copyright © 2011-2022 走看看