• Codeforces Round #714 (Div. 2) 题解(A-D)


    比赛链接

    A题

    大意

    要你构造一个长度为(n(nle 100))的全排列,使得其有(k)个波峰

    波峰的定义为(a[i-1]le a[i]le a[i+1])

    如果有答案任意输出一组答案,否则输出(-1)

    思路

    显然若要构造最多的波峰为在(2,4,6....)这些地方全部占满

    则最多只有(ma=frac{n-1}{2})个波峰

    (k>ma)则直接输出(-1)

    否在在(2,4...2 imes k)(k)个位置构造波峰即可

    构造方法很简单

    首先先设(a[i]=i)

    然后在这(k)个位置中交换(a[i],a[i+1])即可以得到答案

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,k;
    int a[maxn];
    signed main(){
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++) a[i]=i;
            int ma=(n-1)/2;
            if(k>ma){
                printf("-1
    ");
                continue;
            }
            for(int i=1;i<=k;i++){
                swap(a[2*i],a[2*i+1]);
            }
            for(int i=1;i<=n;i++){
                printf("%d ",a[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    

    B题

    题意

    给你一个长度为(n(nle2e5))的数组(a)

    对这个数组进行全排列,看有多少个全排列情况满足对于任意(i)使得

    (a[1]&a[2]&..a[i]=a[i+1]&a[i+2]&..a[n])

    思路

    首先要知道一个简单的性质

    (a&blemin(a,b))

    首先根据题意

    (a[1]=a[2]&a[3]&...a[n])

    (a[1]le a[n])

    (a[n]=a[1]&a[2]&...a[n-1])

    (a[n]le a[1])

    推导为(a[1]=a[n])

    (a[1]&a[2]&.....a[n]=a[1])

    则显然(a[1])必定是这个数组的最小值

    而且由于(a[1]=(a[2]&a[3]&...a[n-1])&a[n])

    那么(a[2],a[3]...a[n-1])任意元素&(a[1])必定还是(a[1])

    所以求出最小值的元素数量(cnt)

    如果(2le cnt)且所有元素(&)(a[1])后还是(a[1])

    那么答案就是(A_{cnt}^2 imes (n-2)!)

    否则答案为(0)

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,k;
    int a[maxn];
    ll fac[maxn];
    signed main(){
        fac[0]=1;
        for(int i=1;i<=2e5;i++){
            fac[i]=fac[i-1]*i%mod;
        }
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            sort(a+1,a+1+n);
            ll cnt=0;
            ll ans=-1;
            for(int i=1;i<=n;i++){
                if(a[i]==a[1]){
                    cnt++;
                }
                if((a[i]&a[1])!=a[1]){
                    ans=0;
                }
            }
            if(ans==-1){
                ans=cnt*(cnt-1)%mod*fac[n-2]%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
     
    

    C题

    大意

    给你一个数字(n(nle 1e9)),进行(m(mle 2e5))次操作

    每次操作数字上的每一位数加(1)

    (1912)经过一次操作后变为(21023)

    (m)次操作后,最后数字的长度(mod;1e9+7)

    思路

    比赛的时候看错题目了,以为求最后变成什么直接自闭

    显然是动态规划

    (dp[i][j])表示(j)数字经过(i)次变化后的长度为多少

    考虑转移方程

    • (j eq9)

    (dp[i][j]=dp[i-1][j+1])

    • (j=9)

    (j=9)则下一步就变成了(10)

    (dp[i][9]=dp[i-1][1]+dp[i-1][0])

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,m;
    ll dp[maxn][10];
    signed main(){
        for(int i=0;i<=9;i++){
            dp[0][i]=1;
        }
        // j走了i步的长度
        for(int i=1;i<=2e5;i++){
            for(int j=0;j<=8;j++){
                dp[i][j]=dp[i-1][j+1];
            }
            dp[i][9]=(dp[i-1][1]+dp[i-1][0])%mod;
        }
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d%d",&n,&m);
            ll ans=0;
            while(n){
                ans=(ans+dp[m][n%10])%mod;
                n=n/10;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
     
    

    D题

    大意

    给你一个长度为(n(nle2e5))的数组(a(1le a[i] le1e9))和一个参数(p(1le ple 1e9))

    • (i)(i+1)有一个长度为(p)的边

    • (gcd(a[i],a[i+1]...a[j])=min(a[i],a[i+1]..a[j])),则(i)(j)有一条长度为(gcd(a[i],a[i+1]..a[j]))的边

    求这个数组的最小生成树

    思路

    观察性质

    (i,j)和可以连边,那么代表这个区间的元素都是(min(a[i],a[i+1]...a[j]))的倍数

    然后本质上是模拟(krushkal)算法

    要发现边要么是(p)要么就是(a[i])

    首先对(a[i])进行排序,然后用双指针来判断区间([l,r])可以用(a[i])使得([l,r])变为一个点,然后对这个区间进行标记。

    使答案加(a[i] imes(r-l)),最后再计算需要长度为(p)来联通的点

    参考(rk_1)的代码

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,p;
    int a[maxn];
    pii pa[maxn];
    bool vis[maxn];
    signed main(){
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d%d",&n,&p);
            for(int i=1;i<=n;i++){
                vis[i]=0;
            }
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                pa[i]={a[i],i};
            }
            sort(pa+1,pa+1+n);
            ll ans=0;
            int rest=n-1;
            for(int i=1;i<=n;i++){
                if(pa[i].fi>p) break;
                if(vis[pa[i].se]) continue;
                int l=pa[i].se,r=pa[i].se;
                while(l>1&&!vis[l]&&a[l-1]%pa[i].fi==0) l--;
                while(r<n&&!vis[r]&&a[r+1]%pa[i].fi==0) r++;
                for(int i=l;i<=r;i++){
                    vis[i]=1;
                }
                rest-=(r-l);
                ans+=1ll*(r-l)*pa[i].fi;
            }
            ans+=1ll*rest*p;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    Django REST framework
    django写入csv并发送邮件
    GC收集器ParNew&CMS
    编写高质量的JavaScript代码
    Vue3.0 declare it using the "emits" option警告
    vue 3.0 router 跳转动画
    vue3.0 element-plus 表格合并行
    element-plus 时间日期选择器 el-date-picker value-format 无效等
    vue3.0中使用,一个元素中是否包含某一个元素。
    vue axios ajax 获取后端流文件下载
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14648992.html
Copyright © 2020-2023  润新知