C言語アルゴリズム学習(数学アルゴリズム、ユークリッド、確率論)

今日は4つの質問しか解決しませんでしたが、これは不快です

解決しました

バースデーケーキ

問題の言い換え:

•ルーシーとリリーは双子で、今日は彼らの誕生日です。母は彼らにバースデーケーキを買った。これで、ケーキはデカルト座標系に配置され、ケーキの中心は(0,0)にあり、ケーキの半径は100です。
•ケーキには2N(Nは整数、1≤N≤50)のサクランボがあります。ママはナイフでケーキを半分に切ります(もちろん直線で)。双子は当然公平に扱われる必要があります。つまり、ケーキの2つの半分は同じ形状である必要があり(つまり、直線はケーキの中心を通過する必要があります)、ケーキの各半分にはN個のチェリーが必要です。彼女を助けてくれませんか?
•ここで、チェリーの座標(x、y)は2つの整数であることに注意してください。この行を2つの整数A、B(Ax + By = 0を表す)の形式で指定すると、AとBは[-500、500]になります。さくらんぼを一直線にすることはできません。テストケースごとに、少なくとも1つの解決策があります。

入る

•入力には複数のテストケースが含まれています。各テストケースは2つの部分で構成されています。最初の部分は1行にNの数字を示し、2番目の部分は2Nの行で構成され、各行には(x、y)を表す2つの数字があります。2つの数字の間には1つのスペースしかありません。入力はN = 0で終了します。

出力

•テストケースごとに、1行を出力し、2つの数値AとBを指定し、2つの数値の間にスペースを入れます。複数のソリューションがある場合は、そのうちの1つを出力するだけです。

質問分析

•この質問の最初の行にNを入力します。これは、ケーキに2N個のサクランボがあることを意味します。次の2N行のそれぞれは、サクランボの座標を示します。ケーキは、原点が中心で半径が100の円であるため、座標値の範囲は[-100、100]です。この質問の出力は一次方程式Ax + By = 0 AおよびBであり、範囲は[-500、500]です。
•この質問は、列挙方法を採用し、[-500、500]の範囲でAとBを列挙し、チェリー座標を線形方程式Ax + Byに代入します。Ax+ Byが0より大きい場合、チェリーは線; 0未満の場合、チェリーは直線の下にあります。0に等しい場合、チェリーは直線上にないため、許可されません。最初のソリューションが生成されるまで列挙します。

ソースコード

#include <iostream>

using namespace std;

const int LEFT = -500, RIGHT = 500;
const int N = 50;
int x[N * 2], y[N * 2];

int main()
{
    
    
    int n;
    while(~scanf("%d", &n) && n) {
    
    
        n *= 2;

        for(int i = 0; i < n; i++)
            scanf("%d%d", &x[i], &y[i]);

        bool flag = true;
        for(int a = LEFT; a <= RIGHT && flag; a++)
            for(int b = LEFT; b <= RIGHT ; b++) {
    
    
                if(a==0 && b==0 ) continue;
                int i, cnt = 0;     // 统计满足AX+BY>0的点数目
                for(i = 0; i < n; i++) {
    
    
                    if(a * x[i] + b * y[i] > 0) ++cnt;
                    else if(a * x[i] + b * y[i] == 0) break;
                }
                if( i < n) continue;
                if(cnt == n / 2) {
    
    
                    printf("%d %d\n", a, b);
                    flag = false;
                    break;
                }
            }
    }

    return 0;
}

Bこれは統合ですか?

問題の言い換え

この図には、AB = BC = CD = DA = aの正方形のABCDがあります。4つの頂点A、B、C、Dを中心とし、aを半径として、4つの円弧を描画します。Aを中心とする円弧は、隣接する頂点Bから始まり、隣接する頂点Dで終わります。その他すべての円弧同様の方法で描画されます。図に示すように、このように3つの異なる形状の領域が正方形に描画され、各領域は異なる色合いで表されます。さまざまな影付きの部分の総面積を計算してください。
ここに画像の説明を挿入

入る

•入力の各行には、正方形の辺の長さを表す浮動小数点数a(0 <a <10000)が与えられます。入力はEOFで終わります。

出力

•入力の各行について、1行を出力し、3つの異なる影付き部分の合計面積を示します:
小数点以下3桁の3つの浮動小数点数を示し、最初の数字は縞模様の領域の総面積を表し、 2番目の数字は点線の領域の総面積を表し、3番目の数字は残りの領域の面積を示します。

サンプル入力

0.1
0.2
0.3

サンプル出力

0.003 0.005 0.002
0.013 0.020 0.007
0.028 0.046 0.016

問題解決

ここに画像の説明を挿入

質問分析

•この質問は正方形の一辺の長さaを与え、3つの異なる影付きの部分の総面積を計算する必要があります。図に示すように、補助線で正三角形を描きます。3つの異なる影付きの部分の領域は、x、y、zで表されます。

ソースコード

#include<iostream>
#include<cmath>
using namespace std;
const double pi=acos(-1);
int main() {
    
    
	double a;
	while(cin>>a) {
    
    
		double z=a*a-pi*a*a/6.0-sqrt(3.0)/4.0*a*a;
		double y=(a*a-pi*a*a/4.0-2.0*z);
		double x=(a*a-4.0*y-4.0*z);
		printf("%.3lf %.3lf %.3lf\n",x,y*4.0,z*4.0);
	}
}/*
        double z = r * r * (1 - PI / 6.0 - sqrt(3.0) / 4);
        double y = r * r * (1 - PI / 4.0 ) - 2 * z;
        double x = r * r  * (PI / 2.0 - 1) - 2 * y;
		*/

C単純除算

問題の言い換え

ここに画像の説明を挿入
被除数nと除数dの間の整数除算演算は、商qと剰余rを生成します。qは、qd≤nおよびr = n−q * dとなるようにqd最大化する整数です
•整数のセットが与えられると、与えられた各整数をdで割ったときに余りが同じになるような整数dがあります。

入る

•入力の各行は、スペースで区切られたゼロ以外の整数のシーケンスを提供します。各行の最後の番号は0であり、このシーケンスには属していません。シーケンスには少なくとも2つ、最大で1000の番号があります。シーケンス内の番号は、すべて同じではありません。入力の最後の行は単一の0を与え、プログラムはこの行を処理する必要はありません。

出力

•入力の各行について、最大の整数を出力して、入力の各整数が同じ余りの数値で除算されるようにします。

サンプル入力

701 1059 1417 2312 0
14 23 17
32122 0 14-22 17 -31 -124 0
0

サンプル出力

179
3
3

問題解決

ソースコード

#include <algorithm>
#include<iostream>
using namespace std;
int gcd(int x,int y) {
    
    
	int r;
	while (x%y!=0) {
    
    
		r=x%y;
		x=y;
		y=r;
	}
	return y;
}
int main() {
    
    
	int a1, a;
	while(~scanf("%d", &a1) && a1) {
    
    
		int g = 0;
		while(scanf("%d", &a) == 1 && a) {
    
    
			int d = a - a1;
			if(d) {
    
    
				if(g) g = gcd(g, d);
				else g = d;
			}
			a1 = a;
		}
		printf("%d\n", abs(g));
	}

	return 0;
}

G-ハンバーガー

問題の言い換え

•クリントンの双子の息子であるベンとビルは10歳の誕生日を祝い、パーティーはニューヨークのサウスブロードウェイ202にあるマクドナルドのレストランで開催されました。パーティーにはベンとビルを含む20人の子供たちが参加しました。ロナルドマクドナルドは、ビーフバーガー10個とチーズバーガー10個を作りました。子供たちに仕えるとき、彼はビルの左側に座っている女の子とビルの右側に座っているベンから始めました。ロナルドは、女の子がビーフバーガーとチーズバーガーのどちらを食べるかを決めるためにコインを投げました。コインの頭の側面はビーフバーガーで、反対側はチーズバーガーです。ベンとビルの番になる前に、ロナルドは他の17人の子供たちとこのプロセスを繰り返しました。ロナルドがベンに来たとき、チーズバーガーはなく、ビーフバーガーは2つしかなかったので、彼はもうコインを投げる必要はありませんでした。
•ロナルド・マクドナルドはこれに非常に驚いたので、この種のことが起こる可能性を知りたがっていました。上記のプロセスでは、ベンとビルが同じハンバーガーを食べる確率を計算してください。ロナルドマクドナルドは常に同じ数のビーフバーガーとチーズバーガーをグリルします。

問題分析

ここに画像の説明を挿入
上の図からわかるように、オフラインを使用して解決できます(初めてオフラインの方法を使用するのは熟練していません)

ソースコード

#include<iostream>
#include<cmath>
using namespace std;
const int N=5e4+7;
int cas,n;
double p[N];
void solve()
{
    
    
	p[1]=1;
	for(int i=1;i<N-1;++i)
		p[i+1]=(2*i-1)*p[i]/(2*i);
}
int main(){
    
    
	solve();
	cin>>cas;
	while(cas--){
    
    
		cin >>n;
		n/=2;
		printf("%.4lf\n",1-p[n]);
	}
	return 0;
}

未解決部分

D-ユークリッド問題

Euclidから、正の整数AとBには、AX + BY = Dとなるような整数XとYが存在することがわかっています。ここで、DはAとBの最大公約数です。問題は、Xに対応するgivenAとBを見つけることです。 YとD。

入力

入力は、スペース
(A、B <1000000001)で区切られた整数AおよびBの行のセットで構成されます

出力

各入力ラインの出力ラインは、スペースで区切られた3つの整数X、Y、およびDで構成されている必要があります。
そのようなXとYが複数ある場合は、| X |のペアを出力する必要があります。+ | Y | 最小限です。最小基準を満たすXとYが複数ある場合は、X≤Yのペアを出力します。

サンプル入力

4 6
17 17

サンプル出力

-1 1 2
0 1 17

問題分析

明らかに、この問題は拡張ユークリッドアルゴリズムで実行する必要があります

int exgcd(int a, int b, int &x, int &y) {
    
    
	if (b==0) {
    
    
		x=1;
		y=0;
		return a;
	}
	int t=exgcd(b, a%b, x, y);
	int x0=x, y0=y;
	x=y0;
	y=x0-(a/b)*y0;
	return t;

}

しかし、私はエアコンを持っておらず、理由を見つけることができません

ソースコード

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int exgcd(int a, int b, int &x, int &y) {
    
    
	if (b==0) {
    
    
		x=1;
		y=0;
		return a;
	}
	int t=exgcd(b, a%b, x, y);
	int x0=x, y0=y;
	x=y0;
	y=x0-(a/b)*y0;
	return t;
}
int main() {
    
    
	int a, b, x, y, d;
	while(~scanf("%d%d", &a, &b)) {
    
    
		d = exgcd(a, b, x, y);
		printf("%d %d\n",x,y);
	}
	return 0;
}

F-確率とは何ですか?

確率は常にコンピュータアルゴリズムの統合された部分です。決定論的アルゴリズムが問題を短時間で解決できなかった場合、確率的アルゴリズムが助けになりました。この問題では、確率的アルゴリズムを扱っていません。特定のプレーヤーの勝率を決定しようとします。
ゲームはサイコロのようなものを投げることによってプレイされます(通常のサイコロのように6つの面があると想定すべきではありません)。プレーヤーがサイコロを投げたときに特定のイベントが発生した場合(3を取得するなど)、そのプレーヤーが勝者として宣言されます。そのようなプレーヤーはN人いる可能性があります。だから最初の
プレーヤーはサイコロを投げ、次に2番目、最後にN番目のプレーヤー、そして最初のプレーヤーというように投げます。プレーヤーが希望のイベントを取得すると、そのプレーヤーは勝者として宣言され、プレーが停止します。これらのプレーヤーのうちの1人(I番目)の勝率を決定する必要があります。

入力

入力には、最初は整数S(S≤1000)が含まれ、入力のセットがいくつあるかを示します。次のS行には、Sセットの入力が含まれます。各行には、プレーヤーの数を示す整数N(N≤1000)、1回のスローで成功したイベントが発生する確率を示す浮動小数点数pが含まれます(成功が3を取得することを意味する場合、pは取得する確率です)通常のダイスの場合、3を獲得する確率は1/6)であり、I(I≤N)は、勝率が決定されるプレーヤーのシリアルです(シリアル番号は1からNまで変化します)。無効な確率§値が入力として与えられないと想定できます。

出力

入力の各セットについて、I番目のプレーヤーが勝つ確率を1行で出力します。
サンプル
出力に示されているように、出力浮動小数点数は常に小数点以下4桁になります。

サンプル入力

2
2 0.166666 1
2 0.166666 2

サンプル出力

0.5455
0.4545

問題分析

ここに画像の説明を挿入
数式を置き換えましたが、エアコンがなく、理由がわかりません

ソースコード

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int main() {
    
    
	int N,i,n;
	double p;
	scanf("%d",&N);
	for(int j=0; j<N; j++) {
    
    
		cin >>n >>p >>i;
		float proba =(pow((1-p),i-1)*p/(1-pow((1-p),n)));
		printf("%.4f\n",proba);
	}
}

今日もまだたくさんの問題が残っています。いつ解決するかわかりません。

おすすめ

転載: blog.csdn.net/seekerzhz/article/details/112910421