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


    A题

    大意

    思路

    显然是把前面的元素放到最后一个

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    //#define b tm
    #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;
    typedef pair<int,int> pii;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n,k;
    int a[maxn];
    signed main(){
        int _;cin>>_;
        while(_--){
            cin>>n>>k;
            for(int i=1;i<=n;i++){
                cin>>a[i];
            }
            int temp=k;
            for(int i=1;i<n;i++){
                if(a[i]>=k){
                    a[i]-=k;
                    k=0;
                    break;
                }else{
                    k-=a[i];
                    a[i]=0;
                }
            }
            int dif=temp-k;
            a[n]+=dif;
            for(int i=1;i<=n;i++){
                printf("%d ",a[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    

    B题

    大意

    给你一个长度为(n(nle 1e3))的数组,每次可以选择两个相邻的数(a[i],a[i+1])使这两个元素变为一个元

    素,值为(a[i]igoplus a[i+1]),判断最后是否存在大于等于(2)个元素,使得所有元素相等

    思路

    若所有元素异或值为(0),那么肯定可以

    但是也有可能出现(3)个相同的元素

    所以再去分为三段去考虑即可

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    //#define b tm
    #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;
    typedef pair<int,int> pii;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n,k;
    int a[maxn];
    int pre[maxn],suf[maxn];
    signed main(){
        int _;cin>>_;
        while(_--){
            cin>>n;
            for(int i=1;i<=n;i++){
                cin>>a[i];
                pre[i]=(pre[i-1]^a[i]);
            }
            suf[n+1]=0;
            for(int i=n;i>=1;i--){
                suf[i]=(suf[i+1]^a[i]);
            }
            bool flag=0;
            for(int i=1;i<=n;i++){
                //[1,i]
                //[i+1,j]
                //[j+1,n];
                for(int j=i+1;j<n;j++){
                    if(pre[i]==suf[j+1]&&pre[i]==pre[n]){
                        flag=1;
                    }
                }
            }
            if(pre[n]==0) flag=1;
            printf(flag?"YES
    ":"NO
    ");
        }
        return 0;
    }
    
    

    C题

    大意

    给你长度为(n(nle 100))的数组(a(1le a[i] le 2e3)),要你删除最少的数,使得这个数组,不能找到

    一些数使得总和为这个数组的一半

    思路

    首先可以(dp)判断是否可以构成一半

    若不能构成那么答案就是(0)

    若能构成肯定删除一个奇数即可,若没有奇数,你可以把所有元素除(2)再找奇数,显然是成立的,所以答

    案必定是(2)的因子数最少

    代码

    #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=1e2+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    typedef pair<int,int> pii;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n,k;
    int a[maxn];
    bool dp[maxn][200005];
    signed main(){
        cin>>n;
        int sum=0;
        int mi=inf,pos=-1;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            sum+=a[i];
            int temp=a[i],cnt=0;
            while(temp%2==0){
                temp=temp/2;
                cnt++;
            }
            if(cnt<mi){
                mi=cnt;
                pos=i;
            }
        }
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=sum;j++){
                if(dp[i-1][j]){
                    dp[i][j]=dp[i][j+a[i]]=1;
                }
            }
        }
        int ans=-1;
        if(sum%2==1||!dp[n][sum/2]){
            ans=-1;
        }else{
            ans=a[1];
        }
        if(ans==-1){
            printf("%d",0);
        }else{
            printf("1
    %d",pos);
        }
        return 0;
    }
    

    D题

    大意

    给你长度为(n(nle 1e5))的数组(a(1le a[i] le1e5))(q(qle 1e5))次查询,每次查询([l,r])最少分为多少段

    才能使每段元素满足相互互质

    思路

    定义(nxt[i])为以(a[i])为起点,向后延申,最近的和(a[i])互质的数的坐标(-1)

    那么可以利用质因子分解,从后往前遍历一边即可得到(nxt)数组

    定义(dp[i])表示以(a[i])为起点,满足题意的区间最远的右边界+1

    那么(dp[i]=min(dp[i+1],nxt[i]))

    (dp[i][j])表示以(i)为起点,走(2^j)

    倍增求解答案即可

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    //#define b tm
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    typedef pair<int,int> pii;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int n,q;
    int a[maxn];
    int nxt[maxn];
    int prime[maxn],cnt;
    int isprime[maxn];
    int pos[maxn];
    int dp[maxn][30];
    void getprime(int n){
        for(ll i=2;i<=n;i++){//开ll因为后面要计算i*prime[j]
            if(!isprime[i]){
                prime[++cnt]=i;
                isprime[i]=i;
            }
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                isprime[i*prime[j]]=prime[j];
                if(i%prime[j]==0) break;
            }
        }
    }
    void rmq(){
        for(int i=1;i<=n;i++){
            dp[i][0]++;
        }
        for(int j=1;j<=20;j++){
            for(int i=1;i+(1<<j)-1<=n;i++){
                dp[i][j]=dp[dp[i][j-1]][j-1];
            }
        }
    }
    int cal(int l,int r){
        int now=l;
        int x=0;
        for(int i=20;i>=0;i--){
            if(dp[now][i]!=0&&dp[now][i]<=r){
                now=dp[now][i];
                x+=(1<<i);
            }
        }
        return x+1;
    }
    signed main(){
        getprime(100000);
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        memset(pos,0x3f,sizeof(pos));
        // 每个位置预处理inf
        for(int i=n;i>=1;i--){
            nxt[i]=n;
            int temp=a[i];
            while(isprime[temp]){
                int x=isprime[temp];
                nxt[i]=min(nxt[i],pos[x]-1);
                while(temp%x==0){
                    temp=temp/x;
                }
                pos[x]=i;
            }
        }
        dp[n][0]=n;
        for(int i=n-1;i>=1;i--){
            dp[i][0]=min(dp[i+1][0],nxt[i]);
        }
        rmq();
        for(int i=1,l,r;i<=q;i++){
            scanf("%d%d",&l,&r);
            printf("%d
    ",cal(l,r));
        }
        return 0;
    }
    
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    Elasticsearch 之 Hello World (二)
    Elasticsearch 之 Hello World (一)
    Linux动态gif图的录制
    Vim配置及说明——IDE编程环境
    Vim自动补全插件----YouCompleteMe安装与配置
    Linux查看硬件信息(北桥芯片组、南桥、PCI接口、CPU等)
    Linux中源码安装编译Vim
    Linux安装搜狗拼音输入法-sogoupinyin
    开始写博客,与ITer们互相学习
    笔记本多硬盘win7下U盘安装Cnetos7引导问题!
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14691810.html
Copyright © 2020-2023  润新知