2020ブルーブリッジカップ第1ラウンドの地方グループBの質問のソリューション(質問あり)

序文

No.4地方大会、今のところ解答はありません。自分で書いてください。もちろん標準的な答えではありません。あくまでも個人的な理解であり、間違いがあるかもしれません。訂正してください。私は個人的に、この地方大会での質問の質は良好で、すべて書き込み可能な質問であり、難易度の勾配も良好だと思います。最後の質問は単純かもしれません。
空白を埋める答えは保存されないので、アイデアの解決策を書いてください。
プログラミングの質問は、後でコードで埋められます。

ランニングトレーニング

カタツムリが木を登る、井戸を登るなど、多くの同様の問題があります。直接計算するか、シミュレーションするようにプログラムできます。ランニングの最後の1分間の残りの体力は、100ではなく400であることに注意してください。

B周年

言うことは何もありません。ただ計算してください。日数を直接取得する機能がExcelにあるそうです。

Cマージ検出

合計が1であると仮定すると、複合テストでは試薬の1 / Kキットを消費する必要があります。このうち、0.01人の感染者は、試薬の0.01 * Kキットを追加で使用する必要があります。つまり、試薬の合計1 / K + K / 100キットが必要です。基本的な不等式に従ってKテイク10。

D REPEATプログラム

翻訳プログラムを作成するか、トリックを使用して置換テキストをコードに変更し、直接実行することができます。
翻訳プログラムを作成すれば、dfsを作成できます。繰り返しが見つかるたびに、新しい呼び出しが行われます。渡されたパラメーターのインデントを使用して優先度を取得します。結果を取得するには、まず長いインデントを計算する必要があります。この行のインデントがパラメータよりも小さい場合は、上位レベルに戻ることができます。
ネストされたREPEATのdfs処理に基づいて、私が作成した翻訳プログラムを提供します

#include <iostream>
#include <cstdio>
using namespace std;

const int maxn = 1000010;
string s[1005];
int i = 0;
int getp(string s)
{
    
    
	int p = 0;
	while(s[p] == ' ')p++;
	return p;
}
int x = 0;
int dfs(int y)
{
    
    
	int p = 0,v = 0;
	while(x<i){
    
    
		x++;
		cout << s[x] << endl << x << ' ' << y << ' ' << v << endl;
		p = getp(s[x]);
		if(p<y){
    
    
			x--;
			return v;
		}
		if(s[x][p] == 'R')
		{
    
    
			v+=(s[x][p+7]-'0')*dfs(p+4);
		}
		else if(s[x][p] == 'A'){
    
    
			v+=s[x][p+8]-'0';
		}

	}
	return v;
}
int main()
{
    
    
    freopen("prog.txt","r",stdin);

    long long ans = 0;
    //getline(cin,s[0]);
    while(!cin.eof()){
    
    
    	getline(cin,s[i]);
    	i++;
    }
    ans = dfs(0);
    cout << ans;
	return 0;
}

Eマトリックス

観察後、左上と右下が取ることができるのは1、2020のみです。1に隣接する2つのグリッド、つまり1行、2列、2行と1列は、2、3しか取ることができません。1列後ろに移動、つまり、1行、3列と2行2列、4と5しか取得できません。合計1009のグループがあると推測すると、答えは2 ^ 1009mod2020になります。

F分割可能シーケンス

タイトルが示すように、入力で直接2によるループ除算を実行します。

Gデコード

先読みモードで出力できます。つまり、一度に2文字を読み取り、2桁目が数値であるかどうかを確認します。そうでない場合は、現在の文字を出力します。そうでない場合は、指定した数値と位置+1の現在の文字を出力します。直接シーケンスすることもできます。出力、数値が読み取られるたびに前の桁を補正します。

Hゴースクエア

単純なdpで十分です。dp[i] [j] = dp [i-1] [j] + dp [i] [j-1]です。
dfsでも解決できますが、値が30に近づくとタイムアウトする場合があります。チャートを作成しました。

整数スプライシング

スプライシング番号は2つの部分で構成されていると見なすことができます。最初の部分はa * 10 ^ b、2番目の部分はcであるため、最初の部分を前処理してから、各cについて最初の部分のような数を問い合わせることができます。 2つの部分の合計modK = 0を満たすには、単にansを追加します。

具体的な方法は、2次元配列modを作成することです。1次元は10の累乗を表し、2次元はmodKの残りを表します。各数値と10、100、1000 ... 10 ^ 9の積modKの剰余を計算し、対応する2次元配列の単位に+1します。処理後のmod [a] [b]は、数値の後に0が続き、modKの残りがbであることを意味します。これは、そのような数値の数です(上記の最初の部分)。次に、各数を処理します。この数が上記のスプライシング数の2番目の部分であると仮定すると、条件modKを満たす最初の部分がこの数modKに追加され、Kを法とする結果は0になります。

処理を容易にするために、渡された値の桁数を返すgetlと10の累乗を返すgetllの2つの関数を書きました。このようにして、各数値aを処理するときに、前処理で取得したmod配列に直接アクセスできます。1つの次元はgetl​​(a)であり、これは最初の部分でいくつの0をたどらなければならないかを意味し、2番目の部分は(Ka modK)modKです。つまり、2つの部分の合計modKは0です。得られた結果は、条件を満たすa * 10 ^ bの数です。

注意する必要があるのは、自分と自分の一致です。つまり、最初の部分のaと2番目の部分のcは同じ数です。処理中に現在の数aにgetll(a)を掛けてKを法とするモジュロかどうか、および必要な剰余(Ka modK)modKと同じかどうかを確認できます。同じである場合、残りの数には現在処理中の数が含まれ、ansは-1でなければなりません。

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int maxn = 100010;
int mod[10][maxn];
long long a[maxn];
int getl(long long a)
{
    
    
	int r = 0;
	while(a>0)
	{
    
    
		r++;
		a/=10;
	}
	return r;
}
long long getll(int a)
{
    
    
	long long r = 1;
	while(a--)r*=10;
	return r;
}
int main()
{
    
    
	int n,k;
	long long ans = 0;
	cin >> n >> k;
	for(int i = 0;i < n;i++)
	{
    
    
		cin >> a[i];
		long long p = 0,q = 1;
		while(p<10)
		{
    
    
			long long t = (a[i]*q)%k;
			mod[p][t]++;
			p++;
			q*=10;
		}
	}
	//cout << mod[1][0] << ' ' << mod[1][1];
	for(int i = 0;i < n;i++)
	{
    
    
		//cout << getl(a[i]) << ' ' << (k-a[i]%k)%k << endl;
		ans+=mod[getl(a[i])][(k-a[i]%k)%k];
		//cout << a[i]*getll(getl(a[i]))%k;
		if((a[i]*getll(getl(a[i])) + a[i])%k == 0)ans--;
	}
	cout << ans;
	return 0;
	
}

Jネットワーク分析

ユニオン検索セットを解くには、各ポイントの重みを最後に見つけるだけでよいので、ユニオン検索セットは各ルート値を更新するだけで済みます。
具体的な方法は、インクリメント配列を設定して、各ユニオンコレクションのポイントのインクリメント値を保存することです。コレクションがマージされるたびに、マージされたセットのルートのインクリメント値から、マージされたセットのルートのインクリメント値を差し引きますこのようにして、最後にポイントの重みを計算するときは、ルートをボトムアップで見つけ、増分値を毎回追加するだけで、ポイントの最終的な重みを取得できます。コレクションをマージすると、ルートノードの親ノードのみが更新され、他のノードの親ノードは引き続きルートノードであり、増分値はルートノードにのみ更新されます。これは、ツリーを生成するために類推でき、リーフノードの重みはルート検索プロセス。

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int maxn = 10010;
int ans[maxn];
int add[maxn];
int fa[maxn];
int v[maxn];
int f(int i)
{
    
    
	if(fa[i]!=i)return f(fa[i]);
}
void uni(int a,int b)
{
    
    
	if(f(a) == f(b)) return;
	else
	{
    
    
		a = f(a),b = f(b);
		if(v[a]>=v[b])
		{
    
    
			add[b]-=add[a];
			fa[b] = a;
			v[a]+=v[b];
		}
		else
		{
    
    
			add[a]-=add[b];
			fa[a] = b;
			v[b]+=v[a];
		}
	}
}
int main()
{
    
    
	int n,m;
	int c = n;
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
    
    
		fa[i] = i;v[i] = 1;
	}
 	for(int i = 0;i < m;i++)
	{
    
    
		int a,b,c;
		cin >> a >> b >> c;
		if(a == 1)
		{
    
    
			uni(b,c);
		}
		else
		{
    
    
			add[f(b)]+=c;
		}
	}
	for(int i = 1;i <= n;i++)
	{
    
    
		int t = i;
		ans[i]+=add[i];
		while(fa[t]!=t)
		{
    
    
			ans[i]+=add[fa[t]];
			t=fa[t];
		}
	}
	for(int i = 1;i <= n;i++)
	cout << ans[i] << endl;
	return 0;
}

タイトルリンク:https
://pan.baidu.com/s/1xcNT6pqKltR_WLhlep64OA抽出コード:5789
プライベートメッセージがあり、それを受け取ります。

おすすめ

転載: blog.csdn.net/qq_39586345/article/details/107174706