Codeforces Educational Round 83 A~E題解

eg:這場似乎比較簡單。E題賽後補的,似乎是區間dp比較簡單的題(之前完全沒學過區間dp呢),B和C真是交的慢了,不然rk能往上升升的。
傳送門

A

題意:判斷A能否整除B

#include "stdio.h"
#include "string.h"
#include "string"
#include "iostream"
#include "algorithm"
#include "vector"
#include "queue"
#include "math.h"
#include "map"
#include "stack"
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e12;
const double eps=1e-6;
int n,m;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int a,b;
        scanf("%d%d",&a,&b);
        if(a%b==0)puts("YES");
        else puts("NO");
    }
    return 0;
}

B

題意:給出一個數組進行重排,問怎麼排使得不存在iaii-a_i相等。
題解:從大到小輸出即可。

#include "stdio.h"
#include "string.h"
#include "string"
#include "iostream"
#include "algorithm"
#include "vector"
#include "queue"
#include "math.h"
#include "map"
#include "stack"
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e12;
const double eps=1e-6;
int n,m,a[maxn];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        for(int i=n;i>1;i--)printf("%d ",a[i]);
        printf("%d\n",a[1]);
    }
    return 0;
}

C

題意:給出n個數字的數組a和一個全0的數組,每一輪操作i可以使得全0數組的任意一個位置加上kik^i,問是否可以把全0數組變成數組a。
題解:將所有數字aia_i轉換成相應的k進制數,保證每一位要麼是1要麼是0,並且同一位置最多隻有一個1。

#include "stdio.h"
#include "string.h"
#include "string"
#include "iostream"
#include "algorithm"
#include "vector"
#include "queue"
#include "math.h"
#include "map"
#include "stack"
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=1e12;
const double eps=1e-6;
int n,m;
ll k;
ll vvis[110],vis[80];
ll a[maxn];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%lld",&n,&k);
        memset(vvis,0,sizeof(vvis));
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        int flag=1;
        for(int i=1;i<=n;i++){
            if(a[i]==0)continue;
            else{
                ll t=a[i];
                int x=0;
                memset(vis,0,sizeof(vis));
                while(t){
                    vis[x]=t%k;
                    t/=k;
                    x++;
                }
                for(int i=0;i<=x;i++)
                    if(vis[i]==1){
                        if(vvis[i]==1)flag=0;
                        else vvis[i]=1;
                    }else if(vis[i]!=0)flag=0;
            }
        }
        if(flag)puts("YES");
        else puts("NO");
    }
    return 0;
}

D

題意:給出n個位置和m個數字(1~m),保證這n個位置最多隻有兩個數字是一樣的,並且保證安排後的數組是先單調遞增後單調遞減的,問最多有多少種安排的方式。
題解:枚舉最大數字i,那麼就是從剩下的數字裏面挑出n-2個數字,接着從挑出來的數字裏選擇一個數字是相等的,最後就是對這n-3個數字進行位置排列,答案即爲i=1mCi1n2Cn212n3\sum_{i=1}^m C_{i-1}^{n-2}*C_{n-2}^1*2^{n-3}


#include "stdio.h"
#include "string.h"
#include "string"
#include "iostream"
#include "algorithm"
#include "vector"
#include "queue"
#include "math.h"
#include "map"
#include "stack"
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll mod=998244353;
const int inf=0x3f3f3f3f;
const ll INF=1e12;
const double eps=1e-6;
ll f[maxn],jc[maxn];
ll quick(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll C(ll n,ll m){
    return f[n]*quick(f[m]*f[n-m]%mod,mod-2)%mod;
}
int main(){
    f[0]=1;jc[0]=1;
    for(ll i=1;i<=200000;i++)
        f[i]=f[i-1]*i%mod,jc[i]=jc[i-1]*2%mod;
    ll n,m;
    scanf("%lld%lld",&n,&m);
    ll ans=0;
    for(ll i=n-1;i<=m;i++){
        ll t=C(i-1,n-2)%mod;
        t=t*C(n-2,1)%mod;
        t=t*jc[n-3]%mod;
        ans=(ans+t)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

E

題意:給出一個數組a,每次可以選擇數組裏相等的兩個相鄰數字ai==ai+1a_i==a_{i+1}合併成ai+1a_i+1,問若干次後,數組剩下的長度是多少。
題解:區間dp的題目。感覺很先進。枚舉區間長度len,接着枚舉起點i,最後枚舉這個區間[i,i+len-1]的分割點k,那麼區間的答案就應該是分割的兩個區間之和dp[i][j]=dp[i][k]+dp[k+1][i+len1]dp[i][j]=dp[i][k]+dp[k+1][i+len-1]。考慮特殊情況會產生合併,如果兩個區間的長度都爲1且數值相等,就代表可以合併。最後答案就是dp[1][n]。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
    ll f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int n,a[510],dp[510][510],f[510][510];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		dp[i][i]=1,f[i][i]=a[i];
	for(int len=2;len<=n;len++){
		for(int i=1;i<=n-len+1;i++){
			int j=i+len-1;
			dp[i][j]=INF;
			for(int k=i;k<=j-1;k++){
				if(dp[i][j]>=dp[i][k]+dp[k+1][j]){
					dp[i][j]=dp[i][k]+dp[k+1][j];
					if(dp[i][k]==1 && dp[k+1][j]==1 && f[i][k]==f[k+1][j]){
						dp[i][j]=1;
						f[i][j]=f[i][k]+1;
					} 
				}
			} 
		}
	} 
	printf("%d\n",dp[1][n]);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章