冬のホリデーキャンプ1.20
記事ディレクトリ
A-バースデーケーキ
トピックの主なアイデア:エキセントリックではなく、ケーキのチェリーを均等に分割します
アイデア:ケーキのすべてのサクランボは座標を持つ点と見なされ、カットは線と見なされ、問題は係数に変換されて、線の上にn点、線の下にn点があることを満たします。ライン上にポイントがあってはなりません
メインコード:
for( i=-500;i<510;i++)
{
int num=0;
for( j=-500;j<500;j++)
{
int num=0;
if(i==0&&j==0)
continue;
for( k=0;k<2*n;k++)
{
if((i*p[k].x+j*p[k].y)>0)
num++;
if((i*p[k].x+j*p[k].y)==0)
break;
}
if(k==2*n&&num==n)
{
x=0;
break;
}
}
if(x==0)
break;
}
完全なコード:
#include<iostream>
#include<stdio.h>
#include<cmath>
using namespace std;
struct note
{
int x,y;
}p[500];
int main()
{
int n,d,i=0,j,k;
while(scanf("%d",&n)&&n)
{
for( i=0;i<2*n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
}
int x=1;
for( i=-500;i<510;i++)
{
int num=0;
for( j=-500;j<500;j++)
{
int num=0;
if(i==0&&j==0)
continue;
for( k=0;k<2*n;k++)
{
if((i*p[k].x+j*p[k].y)>0)
num++;
if((i*p[k].x+j*p[k].y)==0)
break;
}
if(k==2*n&&num==n)
{
x=0;
break;
}
}
if(x==0)
break;
}
printf("%d %d\n",i,j);
}
}
B-これは統合ですか?
トピックの主なアイデア:3つの影付きの部分の領域を見つける
アイデア:補助行を作成して式を見つけます[外部リンク画像の転送に失敗しました。ソースサイトにヒル防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-YxvLoWOx-1611306381252)(C:\ Users \ 29252 \ Pictures \ title \ B1.png)]
自分でやるなら、補助線を作るなんて考えもしません。。。まだ質問が少なすぎて経験が不足しています。数式の質問を作成するのは非常に簡単で、それを押し出すことはできません。。
完全なコード:
#include<iostream>
#include<cmath>
using namespace std;
double a;
#define PI acos(-1.0)
int main() {
while (cin >> a) {
printf("%.3f %.3f %.3f\n", a * a * (1 + PI / 3 - sqrt(3.0)),a * a * (PI / 3 + 2 * sqrt(3.0) - 4), a * a * (-2 * PI / 3 + 4 - sqrt(3.0)));
}
return 0;
}
C-単純な除算
トピックの主なアイデア:与えられた一連のデータに従って、最大の整数を見つけて、各整数の余りを数値で割ったものが同じになるようにします
アイデア:2つの異なる数を除数で除算する余りが同じである場合、2つの異なる数の差は除数の倍数でなければなりません。(最初は本当に考えました)
差を使用して除数を列挙します。したがって、最初に元のシーケンスの最初の差分シーケンスを見つけ、次にすべての非ゼロ要素のGCDを見つけます
メインコード:
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
while (true) {
n = 0;
ans = 0;
cin >> f[++n];
if (f[n] == 0)break;
while (f[n] != 0) cin >> f[++n];
n--;
for (int i = 1; i < n; ++i) {
f[i] = f[i] - f[i + 1];
}
完全なコード:
#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e6 + 10;
int f[N];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main() {
int a, b,n,ans;
while (true) {
n = 0;
ans = 0;
cin >> f[++n];
if (f[n] == 0)break;
while (f[n] != 0) cin >> f[++n];
n--;
for (int i = 1; i < n; ++i) {
f[i] = f[i] - f[i + 1];
}
ans = f[1];
for (int i = 2; i < n; ++i) {
ans = gcd(f[i] == 0 ? ans : f[i], ans);
}
cout << fabs(ans) << endl;
}
return 0;
}
D-ユークリッド問題
知識ポイント:ユークリッドアルゴリズムを拡張する
トピックの主なアイデア:ユークリッドのトスとターンから、正の整数AとBには、そのような整数XとY、AX + BY = Dがあることがわかります。ここで、DはAとの最大公約数です。B。この質問では、特定のAとBについて、対応するX、Y、およびDを見つける必要があります。
アイデア:拡張ユークリッドアルゴリズムを使用して解く
メインコード:
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return d;
}
完全なコード:
#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 d = exgcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return d;
}
int main() {
int a, b;
while (cin >> a >> b) {
int x = 0, y = 0;
int d = exgcd(a, b, x, y);
cout << x << ' ' << y << ' ' << d << endl;
}
return 0;
}
E-デッドフラクション
マイクは必死になって最後の最後に論文を完成させようと奮闘しています。彼は、次の3日間で、すべての研究ノートを漠然と一貫した形にまとめる必要があります。残念ながら、彼は自分の計算が非常にずさんだったことに気づきました。算数を実行する必要があるときはいつでも、電卓に接続して、関連性があると感じた分だけ答えを書き留めました。繰り返し分数が表示されるときはいつでも、マイクは単に最初の数桁に続いて「…」を記録しました。たとえば、「1/3」の代わりに「0.3333…」と書き留めた可能性があります。残念ながら、彼の結果には正確な分数が必要です!彼にはすべての計算をやり直す時間がないので、元の分数を自動的に推定するプログラム(およびFAST!)を作成する必要があります。
これを維持可能にするために、彼は、元の分数が常に、指定された数字のシーケンスを生成する最も単純な分数であると想定しています。最も簡単に言えば、彼は分母が最も小さいものを意味します。また、彼は重要な数字を書き留めることを怠っていなかったと想定しています。小数展開の繰り返し部分の数字は記録されませんでした(この繰り返し部分がすべてゼロであったとしても)。
入力
いくつかのテストケースがあります。テストケースごとに、「0.dddd…」という形式の入力が1行あります。ここで、ddddは1〜9桁の文字列であり、すべてがゼロではありません。0を含む行は、最後のケースの後に続きます。
出力
いずれの場合も、元の分数を出力します。
サンプル入力
0.2...
0.20...
0.474612399...
0
サンプル出力
2/9
1/5
1186531/2500000
トピックの主なアイデア:循環小数を分数に変換します。循環小数に複数の状況がある場合は、分母が最小の分数に変換します。
アイデア:有理数は、m / n、無限ループの小数から小数(0.xxxx)の小数部分nビット、ループ部分ビット、非円形部分naビットの形式で記述できます。
分子:n * 10 ^ n -n / 10 ^分母:(10 (a)-1)*(10(na))そしてgcdによって最も単純な分数に還元されます
この質問はブラザーランのコードを見ました。彼はそれについて話した後で初めてその考えを理解しました。彼がそれをしたとき、彼は小数を変換する方法を知りませんでした、そして彼は規則を見つけませんでした...
完全なコード:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
typedef long long ll;
ll z[11]={1};
string s;
void pre(){
for(int i = 1;i<=10;++i)
z[i] = (z[i-1]<<3)+(z[i-1]<<1);
}
ll gcd(ll a,ll b){
ll c;
while(b){
c=a%b;
a=b;
b=c;
}
return a;
}
int main(){
pre();
while((cin>>s)&&s.size()>1){
ll num = 0;
ll b =0;
for(int i = 2;s[i]!='.';++i){
num = num*10+s[i]-'0';
b++;
}
ll minfz = -1;
ll minfm = -1;
ll fz,fm;
for(int i = 1;i<=b;++i){
fz = num-num/z[i];
fm = (z[i]-1)*z[b-i];
ll g = gcd(fz,fm);
if(fm/g < minfm||minfm==-1){
minfz = fz/g;
minfm = fm/g;
}
}
printf("%lld/%lld\n",minfz,minfm);
}
return 0;
}
F-確率とは何ですか?
主なアイデア:i番目のプレーヤーがk番目のラウンドで勝つ確率を計算します
アイデア:i番目のプレーヤーが最初のラウンドで勝ち、次にi番目のプレーヤーが勝たなかった前のi-1プレーヤー、そして最初のラウンドでi番目のプレーヤーが勝つ確率は(1-p)^です。 (i-1)* p
同様に、i番目のプレーヤーはk番目のラウンドで勝ち、勝つ確率は(1-p)^ {n(k-1)+ i-1} * pです。加算の原理と等比数列の合計式、最初のi人のプレーヤーが勝つ確率は{(1-p)(i-1)* p} *(1 /(1-(1-p) n))
完全なコード:
#include<iostream>
#include<cmath>
using namespace std;
int s, x, i;
double p;
double ans;
int main() {
cin >> s;
while (s--) {
cin >> x >> p >> i;
if(p==0) ans = 0;
else ans = pow(1 - p, i - 1) * p * (1.0 / (1 - pow(1 - p, x)));
printf("%.4f\n", ans);
}
return 0;
}
G-ハンバーガー
トピックの主なアイデア:ベンとビルを含む20人がパーティーに参加し、ビーフバーガー10個、チーズバーガー10個、コイントス、コイントス、コイントス、トスした人がビーフを食べます。それ以外の場合は、チーズが食べられます。質問は、ベンとビルに同じハンバーガーの確率を食べるように頼みます
アイデア:前向きに尋ねるなら、多くの状況があるので、2人が異なるハンバーガーを食べる確率を尋ねてください
私はまだ良い先輩で、このような再帰的な問題についてはよく知っています。自分でやったときは、少し柔軟性がなく、逆に考えるとは思っていませんでした。
メインコード:
#include<iostream>
using namespace std;
const int N = 1e6+6;
int s,n;
double p[N];
int main(){
cin>>s;
p[1] = 1;
for(int i = 1;i<1e6;++i)
p[i+1] = (2*i-1)*p[i]/(2*i);
while(s--){
cin>>n;
n = n/2;
printf("%.4f\n",1-p[n]);//反向思维
}
return 0;
}
H-コイントス
人気のカーニバルゲームでは、グリッド内の正方形のタイルで覆われた領域のあるテーブルにコインが投げられます。賞品は、コインが静止するときにコインで覆われるタイルの数によって決まります。カバーするタイルが多いほど、賞品は高くなります。次の図に、5回のコイントスの結果を示します。
この例では:
- コイン1は1タイルをカバーします
- コイン2は2つのタイルをカバーします
- コイン3は3つのタイルをカバーします
- コイン4は4つのタイルをカバーします
- コイン5は2つのタイルをカバーします
コインがプレイエリアの境界に着地することは許容されることに注意してください(コイン5)。コインがタイルを覆うためには、コインがタイルの正の領域を覆う必要があります。つまり、タイルの境界に触れるだけでは不十分です。コインの中心は、一定の確率でプレイエリアの任意のポイントにある可能性があります。(1)コインは常に平らに置かれ、(2)プレーヤーは、コインの中心が常にプレイエリア(または境界)に置かれることを保証するのに十分であると想定できます。
コインが特定の数のタイルをカバーする確率は、タイルとコインのサイズ、およびプレイエリア内のタイルの行と列の数によって異なります。この問題では、特定の数のタイルをカバーするコインの確率を計算するプログラムを作成する必要があります。
入力
入力の最初の行は、続くケースの数を指定する整数です。いずれの場合も、スペースで区切られた4つの整数m、n、t、およびcが1行に表示されます。プレイエリアは、m行n列のタイルで構成され、それぞれのタイルの長さはtです。使用するコインの直径はcです。1 <= m、n <= 5000、および1 <= c <t <= 1000と想定できます。
出力
ケースごとに、ケース番号を専用の行に印刷します。これに続いて、コインが1タイル、2タイル、3タイル、および4タイルをそれぞれ独自の線で覆う確率が続きます。確率は、小数点以下第4位を四捨五入したパーセンテージで表す必要があります。サンプル出力で指定されている形式を使用します。計算を実行するには、倍精度浮動小数点数を使用する必要があります。「負のゼロ」は、負の符号なしで印刷する必要があります。
連続するケースの出力は空白行で区切ります。
サンプル入力
3
5 5 10 3
7 4 25 20
10 10 10 4
サンプル出力
Case 1:
Probability of covering 1 tile = 57.7600%
Probability of covering 2 tiles = 36.4800%
Probability of covering 3 tiles = 1.2361%
Probability of covering 4 tiles = 4.5239%
Case 2:
Probability of covering 1 tile = 12.5714%
Probability of covering 2 tiles = 46.2857%
Probability of covering 3 tiles = 8.8293%
Probability of covering 4 tiles = 32.3135%
Case 3:
Probability of covering 1 tile = 40.9600%
Probability of covering 2 tiles = 46.0800%
Probability of covering 3 tiles = 2.7812%
Probability of covering 4 tiles = 10.1788%
トピックの主なアイデア:コインを投げて、コインがそれぞれ1、2、3、4個のレンガを占める確率を計算します
アイデア:[外部リンク画像の転送に失敗しました。ソースサイトにヒル防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-CkxoULSM-1611306381261)(C:\ Users \ 29252 \ Pictures \ topic \ H.png)]
再び導関数の質問です。先生の説明を見る前に、本当に始められないと感じました。質問は理解され、コインが占める面積を計算できませんでした。
メインコード:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double PI=acos(-1.0),eps=1e-8;
int main()
{
int x,cnt=0;
cin>>x;
while(x--){
double n,m,t,c,A[5];
scanf("%lf%lf%lf%lf",&n,&m,&t,&c);
A[0]=t*t*n*m;//棋盘面积
A[2] = c*(t-c)*(2*m*n-n-m)+c*(c/2.0)*(2*n+2*m-4);
A[4] = (m-1)*(n-1)*(PI*c*c)/4.0;
A[3] = (m-1)*(n-1)*c*c-(m-1)*(n-1)*(PI*c*c)/4.0;
A[1] = A[0]-A[2]-A[3]-A[4];
printf("Case %d:\n",++cnt);
for(int i=1;i<=4;i++)
printf("Probability of covering %d tile%s = %.4lf%%\n",i,(i==1)?" ":"s",A[i]/A[0]*100.0);
printf("\n");
}
return 0;
}
私-498-bis
本旨:
与えられた多項式に基づく導関数
アイデア:この質問の難しい部分は、入力番号の上限が指定されておらず、配列に保存できないことです。以前にストリーム入力を使用しましたが、結果は正しいです。考慮されていません。提出が間違っています。高齢者は再帰検索を使用しています。定期的です。読んだ後、私は食べ物が多すぎるように感じます。再発:A(i + 1)= A(i)* x + a1;
a0
a0x + a1;
(a0x + a1)x + a2 = a0x ^ 2 + a1x + a2の導出-> 2a1x + a1
(a0x ^ 2 + a1x + a2)x + a3 = a0x ^ 3 + a1x ^ 2 + a2x + a3->求導3a0x ^ 2 + 2a1x + a2->(2a0x + a1)x + a0x ^ 2 + a1x + a2;
後期の導関数は前段の導関数と元の関数で構成されます
後の段階は前の段階より1倍多いので、その導関数は前の段階より係数が1多くなります。
後の段階の導関数は、前の段階に比べて余分な定数を持っています
完全なコード:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int x,a;
char c;
while(~scanf("%d",&x)){
int sum=0,ans = 0;
while(~scanf("%d",&a)){
ans = ans*x+sum;
sum = sum*x+a;
scanf("%c",&c);
if(c=='\n') break;
}
cout<<ans<<endl;
}
}
;
(a0x + a1)x + a2 = a0x ^ 2 + a1x + a2の導出-> 2a1x + a1
(a0x ^ 2 + a1x + a2)x + a3 = a0x ^ 3 + a1x ^ 2 + a2x + a3->求導3a0x ^ 2 + 2a1x + a2->(2a0x + a1)x + a0x ^ 2 + a1x + a2;
後期の導関数は前段の導関数と元の関数で構成されます
後の段階は前の段階より1倍多いので、その導関数は前の段階より係数が1多くなります。
後の段階の導関数は、前の段階に比べて余分な定数を持っています
完全なコード:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int x,a;
char c;
while(~scanf("%d",&x)){
int sum=0,ans = 0;
while(~scanf("%d",&a)){
ans = ans*x+sum;
sum = sum*x+a;
scanf("%c",&c);
if(c=='\n') break;
}
cout<<ans<<endl;
}
}