1. 程式人生 > >Codeforces Global Round 1 (A-E題解)

Codeforces Global Round 1 (A-E題解)

ORC clas 位置 sca 所有 amp long 多少 是否

Codeforces Global Round 1

題目鏈接:https://codeforces.com/contest/1110

A. Parity

題意:

給出{ak},b,k,判斷a1*b^(k-1)+a2*b^(k-2)+...+ak*b^0的奇偶性。

題解:

暴力求模2意義下的值就好了。

代碼如下:

技術分享圖片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
int n;
int b,k;
int a[N];
ll qp(ll A,ll B){
    ll ans 
= 1; while(B){ if(B&1) ans=ans*A%2; A=A*A%2; B>>=1; } return ans; } int main(){ cin>>b>>k; for(int i=1;i<=k;i++) scanf("%d",&a[i]); int t=b%2; int sum = 0; for(int i=k-1;i>=0;i--){ sum=sum+a[k-i]*qp(t,i); sum
%=2; } if(sum&1) cout<<"odd"; else cout<<"even"; return 0; }
View Code

B. Tape

題意:

在[1,m]這個區間中,有n個點,現在要用k個木棍去覆蓋完這些點,問最短覆蓋長度為多少。

題解:

首先將起始點和終點間的距離求出來,然後考慮將不需要的一些覆蓋給減去。

具體做法就是用優先隊列保存兩個相鄰點之間的間隔,然後不斷取最大的間隔減去,最後使得剩下的區間還剩下k個即可。

代碼如下:

技術分享圖片
#include <bits/stdc++.h>
#define
INF 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 1e5+5; int n,m,k; ll a[N],d[N]; ll ans; int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); ans=a[n]-a[1]+1; priority_queue <ll> q; for(int i=1;i<n;i++){ d[i]=a[i+1]-a[i]; q.push(d[i]-1); } int cnt = 1; while(cnt<k){ ll now = q.top();q.pop(); cnt++; ans-=now; } cout<<ans; return 0; }
View Code

C. Meaningless Operations

題意:

有多個詢問,每次詢問會輸入一個數a,然後對於所有的數b(1<=b<a),求max{ gcd(a&b,a^b) }。

題解:

這個可以打表來做。

如果想的話,就是分兩種情況考慮:一種是所有二進制位數都為1,另一種就是並非這樣。

第二種思考起來比較簡單,答案肯定為2^x-1,我們取的b只需要剛好把a二進制中的0填補就行了。

第一種情況會有一個這樣的性質:a&b+a^b=a。現在設g=gcd(a&b,a^b),所以現在有g|a&b,g|a^b,那麽自然有g|a。

我們會發現g其實為a的因子,那麽這種情況找a的最大因子就好啦。

代碼如下:

技術分享圖片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int q;
ll a;
ll p2[30];
ll Print(ll x){
    for(ll i=3;i*i<=x;i++){
        if(x%i==0){
            return x/i;
        }
    }
    return 1;
}
int main(){
    cin>>q;
    p2[0]=1;
    for(int i=1;i<=26;i++) p2[i]=p2[i-1]*2;
    while(q--){
        cin>>a;
        int i;
        for(i=26;i>=0;i--) if((1<<i)&a) break ;
        if(a&(a+1)) cout<<p2[i+1]-1<<endl;
        else cout<<Print(a)<<endl;
    }
    return 0;
}
View Code

D. Jongmah

題意:

給出n個數,數的大小不超過m,問最多有多少個類似於(x,x,x),(x-1,x,x+1)這樣的三元組,每個數最多用一次。

題解:

對於我這樣的蒟蒻來說,dp方程式理解了很久,感覺十分巧妙。

首先,就是對於類似於(x-1,x,x+1)這樣的三元組來說,我們只需要考慮不超過三個的情況就可以了。因為當其超過三個時,直接選(x,x,x)這種類型得到的答案是一樣的。

設dp(i,j,k)的定義為:當前在i這個位置,有j個(i-1,i,i+1)三元組,有k個(i,i+1,i+2)這樣的三元組。

轉移的話就從(i-2,i-1,i),(i-1,i,i+1) (即i-1)轉移過來,我們在計算的時候附加上(x,x,x)這種類型就好了。

因為每次都從i-1轉移過來,所以還可以用滾動數組優化掉一維,但是不優化對於這題也沒啥影響~

代碼如下:

技術分享圖片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
int n,m;
int a[N],dp[N][3][3];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        a[x]++;
    }
    for(int i=1;i<=m;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++){
                for(int l=0;l<3;l++){
                    if(l+j+k>a[i]) continue ;
                    dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+l+(a[i]-l-k-j)/3);
                }
            }
        }
    }
    cout<<dp[m][0][0];
    return 0;
}
View Code

E. Magic Stones

題意:

給出兩個數列{cn},{tn},現在可以進行一些變化,比如對於ci來說,可以讓ci=ci-1+ci+1-ci (2<=i<n),變化的次數以及位置不限,問是否最後能得到t數列。

題解:

這題也比較巧妙吧,首先判斷一下首尾可以知道是否可行。

之後根據這個式子,利用差分數組來解。

設di=ci+1-ci,那麽當ci變化後,di=ci‘-ci-1=ci+1-ci=di+1,di+1=di,也就是說,兩個差分數組相當於換了下位置。

也就是說,題目中的操作,實質上是不斷交換差分數組的位置。

之後就有很多種方法了,給出我的代碼吧:

技術分享圖片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int n;
ll c[N],t[N],d[N];
multiset <ll> s;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    for(int i=1;i<=n;i++) scanf("%d",&t[i]);
    if(c[1]!=t[1] || c[n]!=t[n]){
        cout<<"No";
        return 0;
    }
    for(int i=1;i<n;i++) d[i]=c[i+1]-c[i],s.insert(d[i]);
    for(int i=2;i<=n;i++){
        ll need = t[i]-t[i-1];
        auto it = s.lower_bound(need);
        if(*it==need){
            s.erase(it);
        }else{
            cout<<"No";
            return 0;
        }
    }
    cout<<"Yes";
    return 0;
}
View Code

除開這種,還可以求出t數列的差分數組,然後對兩個差分數組進行排序來比較,實現方法比我簡單多了。

Codeforces Global Round 1 (A-E題解)