1. 程式人生 > 其它 >濟南賽補題

濟南賽補題

技術標籤:訓練題解ACMacm競賽

M題

  • 題目

In China, there is a very famous problem about pancakes: You have a pan and you can fry two pancakes at the same time each time. For a pancake, its front and back sides need to be cooked, and it takes one hour for each side to be cooked.

So how long does it take at least to cook 3 pancakes? The answer is three hours:

In the first hour, fry the front of No.1 pancake and the front of No.2 pancake.

In the second hour, fry the back of No.2 pancake and the front of No.3 pancake.
In the third hour, fry the back of No.1 pancake and the back of No.3 pancake.
Now you have a pan and you can fry KK pancakes at the same time each time. How many hours does it takes at least to cook NN pancakes?

It’s noticed that you have to fry some side of the pancake until fully cooked every time, it means that you can’t fry some side of the pancake half-cooked and taking it out. So the answers are always integers.

  • 題意

一口鍋可以同時煎制k個餅,每張餅兩面都需要煎制,每一面需要煎1小時,問最快把n張餅全部煎好需要多少小時

  • 思路

共有n張餅就意味著如果一張一張煎制的話總時間是2n 但是現在可以同時煎制

如果2 ∗ n % k = 0 2n%k=02∗n%k=0 就可以每次都放上去k張,這樣答案就是2 ∗ n / k 2n/k2∗n/k
如果2 ∗ n % k ! = 0 2
n%k!=02∗n%k!=0 就可以像題目那樣交叉著煎制,到最後把小於k的剩餘餅全都放上去煎制好就成了,答案是2 ∗ n / k + 1 2*n/k+12∗n/k+1

  • 程式碼
#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    int n,k;
    cin>>n>>k;
    int now = 2 * n / k + (2 * n % k == 0?0:1);
    if(now < 2) now = 2;
    cout<<now;
}
 
/*
 
4 2 4
4 3 3
4 4 2
4 5 2
4 6 2
4 8 1
 
*/

G題

  • 題目

題目描述
MianKing has one integer XX, he wants to perform some operations to transform XX to YY (Y<X)(Y<X).
In each operation, MianKing can choose one integer 0\leq A<X0≤A<X and let X=XxorAX=X xor A.
it’s noticed that after an operation, the upper bound of AA will change because XX has changed.
Now you need to help MianKing to find a way to transform XX to YY by doing at most 55 operations.

輸入描述:
The first line has two integers X,YX,Y.

1 < = Y < X < = 1 0 18 1<=Y<X<= 10^{18} 1<=Y<X<=1018
1 ≤ Y < X ≤ 1 0 18 1≤Y<X≤10^{18} 1Y<X1018
.

輸出描述:
The first line has one integer d denotes the number of operations you did.
Then there are d integers A 1... d A_{1...d} A1...d
0 ≤ d ≤ 5 0≤d≤5 0d5.

  • 思路

    如果 X x o r Y < X X xor Y<X XxorY<X 那就直接異或 X^Y 否則先異或上Y,再異或上X。

  • 程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll X,Y;cin>>X>>Y;
    if((X^Y)<X)
    {
        printf("1\n");
        printf("%lld\n",X^Y);
    }
    else
    {
        printf("2\n");
        
        cout<<Y<<" "<<X<<endl;
    }
}

C題

  • 題意
    a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3 堆數量分別為1,2,3 的石子,每次合併花費為 ( x m o d 3 ) ∗ ( y m o d 3 ) (x~mod ~3)*(y~mod~3) (xmod3)(ymod3), 問合成一堆最小花費是多少?
  • 思路
    這題太簡單了,直接一發 A C ~AC~ AC。就是分類討論就可了,直接看程式碼。
  • 程式碼
#include<iostream>

using namespace std;

int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    int res=0;
    if(a<b)
    {
        res+=(a*2);
        b-=a;
        int x=b/3;
        res+=x*6;
        if(b%3==2)
            res+=4;
        cout<<res<<endl;
    }
    else if(a==b)
    {
        cout<<2*a<<endl;
    }
    else
    {
        res+=2*b;
        a-=b;
        int x=a/3;
        res+=x*3;
        if(a%3==2)
            res+=1;
        cout<<res<<endl;
    }
}

D題

  • 題意
    n個同學,每個同學寫論文的字數區間 [ l , r ] [l,r] [lr],與此同時他們的成績是 n − k i n-k_i nki k i k_i ki 是指比他字數寫的多的人的個數。這題給了一個初始 p l a n plan plan,就是每個人按自己的字數最大值去寫,所以每個人都有一個初始成績,但是,為了儘量的縮短需要寫的論文的字數,並保證成績不會低於初始成績的條件下,求 ∑ i = 0 n w i \sum_{i=0}^n w_i i=0nwi 最小值。
  • 思路
    貪心。按照 R R R 為第一關鍵字、 L L L 為第二關鍵字排序。 R R R相同的直接去所有能滿足條件的最小的就行。注意要始終更新每個區間能滿足的最小值。
  • 程式碼
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e5+10;
struct node {
	ll l,r;
}X[N];

bool cmp(node a,node b)
{
	if(a.r==b.r)
		return a.l<b.l;
	return a.r<b.r;
}


int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>X[i].l>>X[i].r;
	}
	sort(X+1,X+1+n,cmp);
	ll last=X[1].r;
	ll res=0;
	int k=1;
    ll m=X[1].l;
	for(int i=2;i<=n;i++)
	{
		if(X[i].r==last)
		{
			k++;
		}
		else
		{
            m=max(m,X[i-1].l);
			res+=(k*m);
			last=X[i].r;
			k=1;
		}
	}
	res+=(k*max(m,X[n].l));
	cout<<res<<endl;
}