2021-01-13トレーニング問題の解決策

コンテスト

一。A.フェニックスとバランス

1.効果:

2から2 ^ nまでのn個の数があります。それらをランダムに2つの山に分割し(各山はn / 2)、nが偶数であることを確認して、n /の2つの山の合計の差を求めます。 2つの数字が最小です

2.問題解決:

ルールを探すと、1つの山に分かれていることがわかりました:2 n / 2、2 n / 2 + 1、...、2 n-1、(合計n / 2の数)、
もう1つの山は・:2 1、2 2、... 2 N / 2-1、2 N
、この場合、両者の差が最小である。
式である:2 N / 2 + 1 -2
用途は満たすためにPOW T、高速電力を使用

他の人の方法を読んだ後、それは前の数* 2 + 2でもあり得ることがわかりました、本質はほとんど同じです

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
typedef long long ll;
ll quick_pow(ll a,ll b) {
    
    
    ll ans = 1;
    while(b) {
    
    
        if(b&1)
            ans *= a;
        a *= a;
        b >>= 1;
    }
    return ans;
}
int main(){
    
    
	int t;
	int n,i;
	long long int a[40];
	for(i=2;i<=32;i+=2){
    
    
		a[i]=quick_pow(2,i/2+1)-2;
	}
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n;
			cout<<a[n]<<endl;
		}
	}
 
}

二。G.奇数の選択

1.効果:

n個の数の配列があります。n個の数からx個の数を選択し、それらの合計を奇数にします。はいの場合、はい、いいえいいえ

2.問題解決:

まず、絶対に不可能ないくつかの特殊なケースを除外し
ます。1。すべて偶数
2.すべて奇数、ただしxは偶数
3. n == xの
場合、合計が偶数/奇数である残りのケースは偶数です。問題はx <nであることが保証されています。常に最初に偶数を見つけ、偶数に応じて奇数を調整し、最終結果を奇数にすることができます。

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
typedef long long ll;

int main(){
    
    
	int n;
	int t;
	int x;
	int odd,even;
	int a[1001];
	while(cin>>t){
    
    
		while(t--){
    
    
			odd=0;
			even=0;
			cin>>n>>x;
			for(int i=0;i<n;i++){
    
    
				cin>>a[i];
				if(a[i]%2==0)
				even++;
				else
				odd++;
			}
			if(n==even)
			printf("No\n");
			else if(n==odd && x%2==0)
			printf("No\n");
			else if(n==x&&odd%2==0)
			printf("No\n");
			else
			printf("Yes\n");
			
		}
	}
 
}

三。H.サブシーケンスの憎悪

1.効果:

文字列sには0/1しかありません。文字列のサブシーケンスに「010」/「101」がある場合、文字列は適切ではありません。文字列内の特定の位置の数を調整して、0-を設定できます。 > 1 / 1-> 0、この文字列を適切にするために、少なくともいくつ変更するかを尋ねます。すべてを変更できます。

2.問題解決:

明らかに、それは最終的に実現する必要があります。左側のすべての1と右側のすべての0、または左側のすべての0と右側のすべての1は
dpと見なされます。2つのdp、1つは必要な数を記録しますi番目の位置で変更され、左側に1、右側に0、その他のレコード別のケースでは、最小のものを見つけて
sum0を使用してすべての0を記録し、sum1はすべての1を記録します。x0
は次の位置を記録します。前の0、x1はです。1、
左と右の1 0の場合、変更するのが適切です:x0 + sum1-x1
左1と右の0の場合、変更するのが適切です:x1 + sum0-x0
最小値を見つけます

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
typedef long long ll;

int main(){
    
    
	int t,n,i,j;
	char s[2000];
	while(cin>>t){
    
    
		while(t--){
    
    
			scanf("%s",s);
			n=strlen(s);
			int sum0=0,sum1=0;
			int x0=0,x1=0;
			for(i=0;i<n;i++){
    
    
				if(s[i]=='0')
				sum0++;
				else
				sum1++;
			}
			int out=2000;
			for(i=0;i<n;i++){
    
    
				if(s[i]=='0')
				 x0++;
				else
				 x1++;
				out=min(out,min(x1+sum0-x0,x0+sum1-x1));
			}
			cout<<out<<endl;
		}
	}
 
}

四。B.フェニックスとビューティー

1.効果:

n個の数値が与えられた場合、その中の任意の位置に任意の数値を追加して、配列内のm個の連続する数値の合計を同じにすることができます。可能であれば、配列番号の数を出力し、そうでない場合は、-1を出力します。

2.問題解決:

n個の数の中にm個以上の異なる数がある場合、それは不可能です.m = 3とすると、配列はa、b、c、d、a、b、c、dであり、a + b + cになります。 = b + c + d
n個の数がm個ある場合は、m個をn回コピーします。n個がm個
未満の場合は、m個に加算し、m個をn回繰り返します。

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#define N 300010
using namespace std;
typedef long long ll;
int a[N],b[N];
set<int> s;
	
int main(){
    
    
	int t,n,k;
	int i,j;

	while(cin>>t){
    
    
		while(t--){
    
    
			s.clear();
			cin>>n>>k;
			memset(b,0,sizeof(b));
			memset(a,0,sizeof(a));
			for(i=0;i<n;i++){
    
    
				cin>>a[i];
				s.insert(a[i]);
			}
			int n1=s.size();
			if(n1>k){
    
    
				printf("-1\n");
				continue;
			}
			j=1;
			while(s.size()<k){
    
    
				s.insert(j);
				j++;
			}
			set<int>::iterator iter;
			int x=0;
			for(iter=s.begin();iter!=s.end();iter++){
    
    
				b[x++]=*iter;
			}
			printf("%d\n",n*x);
			for(i=0;i<n-1;i++){
    
    
				for(j=0;j<x;j++){
    
    
					printf("%d ",b[j]);
				}
			}
			for(j=0;j<x-1;j++){
    
    
				printf("%d ",b[j]);
			}
			printf("%d\n",b[j]);
		}
	}
} 

五。I.葉のゲーム

1.効果:

n個のノードを持つ根なしツリーを考えると、2人が交代で取り、リーフノードを取り、彼に接続されているエッジを削除できるたびに、xを取得した人、勝った人を削除します。

2.問題解決:

ゲームでは、誰もが最適な
ノードを選択します。注:xが最初にリーフノードであり、ツリーにノードが1つしかない
場合、残りのケース> = 2の場合、最初の手がxに接続されたエッジを獲得します。どちらも最善の解決策です。この場合、最終的には次の図になります。
ここに画像の説明を挿入
このとき、最初の動きは無効になります。
どちらもサブツリーを完成させたくないので、そうでなければxは葉になります。したがって、2人は間違いなく2つのサブツリーを残し、他に取得する方法がなくなるまでxを葉に変えます。したがって、これは上記の場合です。

そうすれば、nのパリティを判断するだけで誰が勝つかを判断できます。

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#define N 300010
using namespace std;
typedef long long ll;
int a[N],b[N];
int main(){
    
    
	int t;
	int x,n;
	int u,v;
	int i;
	while(cin>>t){
    
    
		while(t--){
    
    
			memset(a,0,sizeof(a));
			cin>>n>>x;
			for(i=0;i<n-1;i++){
    
    
				cin>>u>>v;
				a[u]++;
				a[v]++;
			}
			if(a[x]<=1||n%2==0){
    
    
				printf("Ayush\n");
			}else{
    
    
				printf("Ashish\n");
			}
		}
	}

} 

六。C.フェニックスと流通

1.効果:

長さnの文字列を指定し、それをk個の部分に分割し、
辞書式順序が最大になるサブシーケンスが最小になるように順序を調整します。辞書式サイズ:a <b、ab <abb、abc <ac ...
この質問つまり、これは、最大の辞書式順序を持つk個のサブ文字列の1つが存在する必要があるため、最大の辞書式順序は可能な限り小さくなります。

2.問題解決:

参照
最初に文字列を並べ替え、これに従って分割し
ます最大と最小が必要な場合は、最初のkと最後のnkの組み合わせである必要があります。辞書式順序は
、最初のkかどうか判断するために可能な限り小さくなります。文字は同じです。異なる場合は、最初のs [k]が配置されている文字列は、辞書式順序で最大である必要があります。最小にする方法は、文字列にs [k]のみがあり、残りのnkがあることです。文字は、abbb | ccccなどのs [k]未満の文字に割り当てられ、accc、b、b、bに分割されます。
前の文字が同じである
場合は、次のnk文字が同じであるかどうかを判断します。同じ、aaa | bbbbのように、後者のnk文字は均等に分散さ
れます。aaa| bbcのように違いがある場合、nkの異なる文字大小でなければならないため、後者はaに割り当てられます。分離されると、後ろの大きなものが前に走って大きくなります。辞書式順序で並べると最小になります。ac> abbcなど

3.acコード:

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#define N 300010
using namespace std;
typedef long long ll;
char s[N];
int main(){
    
    
	int t;
	int n,k;
	int i;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>n>>k;
			scanf("%s",s);
			sort(s,s+n);
			int flag=0;
			for(i=1;i<k;i++){
    
    
				if(s[i]!=s[i-1])
				flag=-1;
			}
			if(flag==-1){
    
    
				printf("%c\n",s[k-1]);
			}else{
    
    
				for(i=k+1;i<n;i++){
    
    
					if(s[i]!=s[i-1])
					flag=-1;
				}
				if(flag==-1){
    
    
					printf("%c",s[k-1]);
				   for(i=k;i<n;i++){
    
    
					printf("%c",s[i]);
				    }
				    printf("\n");
				}else{
    
    
					int x=(n-k)/k;
					printf("%c",s[k-1]);
					for(i=k;i<k+x;i++){
    
    
						printf("%c",s[i]);
					}
					if((n-k)%k!=0)
					printf("%c",s[k]);
					printf("\n");
				}
				
			}
		}
	}
	


} 

七。D.フェニックスと科学

1.効果:

2.問題解決:

3.acコード:

おすすめ

転載: blog.csdn.net/weixin_46064382/article/details/112703786