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;
}

卷也卷不过,躺又躺不平
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14691810.html