• 【2019 10th C++】 蓝桥杯决赛


    (checkmark)

    题意

    (2019<X<Y),使得(2019 imes 2019 , X imes X , Y imes Y)构成等差数列,且(X+Y)的值尽量小

    题解

    枚举(X)的值,只要(X)的值确定了,得到(Y),通过开根后平方判断是不是一个整数

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    
    int main(){
        int X,Y;
        int a=2019*2019;
        rep(i,2020,100000){
            int del=i*i-a;
            double y2=i*i+del;
            int y=sqrt(y2);
            if(y*y==y2){
                X=i,Y=y;
                break;
            }
        }
        cout<<X+Y<<endl;
    }
    

    答案

    7020
    

    (checkmark)

    题意

    求解两两不同的素数构成(2019)的方案数

    题解

    (01)背包求数字部分和问题

    • (dp[0sim cnt][0])的边界问题

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define ll long long 
    const int N=2019+10;
    ll dp[N][N];
    int primes[N],cnt;
    bool st[N];
    void get()
    {
        rep(i,2,2019)
        {
            if(!st[i]) primes[++cnt]=i;
            for(int j=1;primes[j]<=2019/i;j++)
            {
                st[primes[j]*i]=1;
                if(i%primes[j]==0) break;
            }
        }
    }
    
    int main()
    {
        get();
        rep(i,0,cnt) dp[i][0]=1;
    
        rep(i,1,cnt) rep(j,1,2019)
        {
            dp[i][j]=dp[i-1][j];
            if(j>=primes[i]) dp[i][j] += dp[i-1][j-primes[i]];
        }
            
        cout<<dp[cnt][2019]<<endl;
    }
    

    答案

    55965365465060
    

    (checkmark)

    题意

    求约数个数为(100)的最小整数

    题解

    从小到大暴力枚举即可

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    
    int main()
    {
        int ans;
        for(int i=2;;i++)
        {
            int d=0;
            for(int j=1;j<=i;j++)
            {
                if(i%j==0) d++;
            }
            if(d==100)
            {
                ans=i;
                break;
            }
        }
        cout<<ans<<endl;
    }
    

    答案

    45360
    

    题意

    将一个(7 imes 7)的方格沿着边剪开后,右半部分水平翻转后再旋转拼接在左边那块的不规则处,要求拼成的还是一个矩形,求有多少种裁剪方法

    题解

    Code

    
    

    (checkmark)

    题意

    有一个(7 imes 7)的方格。方格左上角顶点坐标为((0,0)),右下角坐标为((7,7))
    求满足下列条件的路径条数:

    1、起点和终点都是((0,0))

    2、路径不自交

    3、路径长度不大于(12)

    4、对于每一个顶点,有上下左右四个方向可以走,但是不能越界。

    题解

    • (dfs)所有可能的行走方向,在每一个(dfs)路径中,标记已经走过的节点,不能重复行走

    • 当满足走到((0,0))(step;!=;0,stepleq 12),累计答案

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    
    const int N=15;
    int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    bool st[N][N];
    int ans;
    void dfs(int x,int y,int step)
    {
        if(step>12) return;
        if(!x && !y && step<=12 && step)
        {
            ++ans;
            return;
        }
        rep(i,0,3)
        {
            int tx=x+dx[i],ty=y+dy[i];
            if(tx >= 0 && tx<7 && ty >= 0 && ty<7)
            {
                if(st[tx][ty]) continue;
                st[tx][ty]=1;
                dfs(tx,ty,step+1);
                st[tx][ty]=0;
            }
        }
    }
    int main()
    {
        dfs(0,0,0);
        cout<<ans<<endl;
    }
    

    答案

    208
    

    六. 最优包含(checkmark)

    题意

    给定两个字符串(A)(B),保证(A)的长度不小于(B)的长度,问至少修改(A)的多少个字符,可以令(B)成为(A)的子序列。

    题解

    子序列不是连续的,所以只要下标的大小关系不变并且包含(B)的每一个字母即可

    • (dp[i][j])表示(A)的前(i)个包含(B)的前(j)个的操作次数

    • 状态转移:(dp[i][j]=min(dp[i-1][j],dp[i-1][j-1]+(A[i]!=B[j])))

    注意开始边界的定义(dp[0][0]=0)

    数据范围

    (1leq |A|,|B|leq 1000)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    const int N=1010;
    char a[N],b[N];
    int dp[N][N];
    int n,m;
    int main(){
        scanf("%s%s",a+1,b+1);
        n=strlen(a+1);m=strlen(b+1);
        memset(dp,0x3f,sizeof dp);
        rep(i,0,n) dp[i][0]=0; 
        rep(i,1,n) rep(j,1,m){
            dp[i][j]=dp[i-1][j];
            dp[i][j]=min(dp[i][j],dp[i-1][j-1]+(a[i]!=b[j]));
        }
        printf("%d
    ",dp[n][m]);
    }
    

    七. 排列数字

    题意

    对于一个数列中的某个数,如果这个数比两侧的数都大或比两侧的数都小,我们称这个数为这个数列的一个转折点。
    如果一个数列有(t)个转折点,我们称这个数列为(t+1)调数列。
    给定两个正整数(n,k)。求在(1sim n)的全排列中,有多少个数列是(k)调数列。

    数据范围

    (1leq kleq nleq 500)

    题解

    • (dfs)求数字的全排列,判断当前是否存在(k-1)个转折点,如果是的话累计个数

    • 可行性剪枝,如果转折点超过或者加上剩下的所有点数都不够就剪枝

    • 每次递归开始的时候累加转折点,所以判断的时候要(+1)因为在(u=n+1)的时候存储了(n)个值的全排列

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    const int N=1010;
    int n,k;
    int path[N];
    int ans;
    bool st[N];
    int a[N];
    bool check(int x)
    {
        if(path[x-1]>path[x]&&path[x]<path[x+1]) return 1;
        if(path[x-1]<path[x]&&path[x]>path[x+1]) return 1;
        return 0;
    }
    void dfs(int u,int sum)
    {
        if(u>=4) // 边界问题
        {
            if(check(u-2)) sum++;
        }
        if(u == n+1)
        {
            if(sum== k-1) ans++;
            return;
        }
    
        if(sum > k-1 || sum+n-u+1 < k-1) return;
        rep(i,1,n)
        {
            if(st[i]) continue;
            st[i]=1;
            path[u]=i;
            dfs(u+1,sum);
            st[i]=0;
        }
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        dfs(1,0);
        printf("%d
    ",ans);
    }
    

    八.解谜游戏

    题意

    题解

    Code

    
    

    九. 第八大奇迹(checkmark)

    题意

    给定一个长度为(n)的序列,初始所有的值都为(0),给定(m)个操作,操作有两种

    • ((C,x,y)):将第(x)位置上的值修改为(y)

    • ((Q,x,y)):查询问下标为(xsim y)区间中的第(8)大数字

    数据范围

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

    题解

    每次求的只有第(k)大的数字,所以线段树的每个节点利用(vector)维护当前区间内部的前(8)大的数字

    • (vector)每次(push\_back)都需要动态增加空间,导致(TLE),所以在初始化过程中通过(resize)将其变为数组

    • 每次修改操作后通过引用的方式改变更新节点前八大的数字

    数组不能作为函数返回值,所以需要用(vector)作为数组进行使用

    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,m;
    struct node {
        int l,r;
        vector<int>p;
        #define l(u) u*2
        #define r(u) u*2+1
    }tr[N*4];
    void pushup(vector<int>&u,const vector<int>&left,const vector<int>&right){
        int i=0,j=0,cnt=0;
        rep(t,1,8){
            if(left[i]>=right[j]) u[cnt++]=left[i],i++;
            else u[cnt++]=right[j],j++;
        }
    }   
    
    void build(int u,int l,int r){
        tr[u].l=l;
        tr[u].r=r;
        tr[u].p.resize(8);
        if(l==r){
            tr[u].p[0]=0;
            return;
        }
        int mid=l+r>>1;
    
        build(l(u),l,mid);
        build(r(u),mid+1,r);
    }
    
    void modify(int u,int id,int x){
        if(tr[u].l==tr[u].r){
            tr[u].p[0]=x;
            return;
        }
    
        int mid=tr[u].l+tr[u].r>>1;
        if(id<=mid) modify(l(u),id,x);
        else modify(r(u),id,x);
    
        pushup(tr[u].p,tr[l(u)].p,tr[r(u)].p);
    }
    vector<int> query(int u,int l,int r){
        if(tr[u].l >= l && tr[u].r <= r) return tr[u].p;
        int mid=tr[u].l+tr[u].r>>1;
    
        if(r<=mid) return query(l(u),l,r);
        if(l>mid) return query(r(u),l,r);
    
        vector<int>ans(8,0);
        pushup(ans,query(l(u),l,r),query(r(u),l,r));
        return ans;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        char op[2];int x,y;
        build(1,1,n);
        while(m--){
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='C') modify(1,x,y);
            else printf("%d
    ",query(1,x,y)[7]);
        }
        return 0;
    }   
    

    十.燃烧权杖

    题意

    数据范围

    题解

    Code

    
    
  • 相关阅读:
    Python常用模块学习
    如何在cmd下切换不同版本的Python
    Python3
    Python第二模块(文件和函数)
    Hibernate教程一览
    struts2框架一览
    Java正式day_04——嵌套循环
    AJAX
    JS+JQUERY
    Mybatis注意问题
  • 原文地址:https://www.cnblogs.com/hhyx/p/13893551.html
Copyright © 2020-2023  润新知