1. 程式人生 > >牛客寒假算法基礎集訓營3(部分)

牛客寒假算法基礎集訓營3(部分)

lin 小姐 print 簡單 計劃 sum string 題意 定制

傳送門:點我

C題:處女座點名

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

技術分享圖片

處女座覺得自己手上的經費可能不太夠,於是決定給牛逼學生們帶家教。

一天他去上課用自己的火眼金睛感覺教室裏有一個學生沒有來,於是他就叫學生們報出自己的學號。

已知這個班上的學號是從1開始連續編號的,處女座告訴你這個班上有多少人,想問問你到底是誰沒有來。

輸入描述:

輸入數據共兩行,第一行為一個整數N,表示班上的學生數量。

第二行為一行N-1個整數,表示已經來的學生的學號,按升序給出。

輸出描述:

輸出一個整數,為沒有來的學生的學號。
示例1

輸入

3
1 3

輸出

2

備註:

2N200,000


按題意做就行
代碼:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int n;scanf("%d",&n);
    int ans = n;
    
for(int i = 1 ; i <= n-1 ; i++){ int x; scanf("%d",&x); if(x != i &&ans==n){ ans = i; } } printf("%d\n",ans); } /* 3 1 3 */

D題:處女座的訓練

題目描述

處女座靠著自己的家教本領賺夠了去比賽的錢,於是開啟了瘋狂訓練。在每個夜深人靜第二天不收作業的夜晚,他都會開始刷題。

"今日又是一個刷題的夜晚。"他挑選了n道題開始刷,而題太多,刷不掉,理還亂(嗚嗚)、自己沒有解決的題目每分鐘都會給他帶來
bibi的疲倦值,而解決每一道題目都需要花費aiai分鐘的時間。

當然,處女座一般都是考慮清楚了再寫題的,所以他在寫題的時候都會精神抖擻,也就是說,當前正在寫的那一題並不會給他帶來任何疲勞。

為了迎接後天要收的作業和明天要遇到的小姐姐,他想讓今晚的刷題盡可能的輕松,那請你幫他找出最小所需要的疲倦值吧。

輸入描述:

輸入數據共包括n+1行,第一行包括一個n表示處女座今晚打算訓練的題的數量。

接下來n行,每行包括兩個整數ai,biai,bi,分別表示處女座刷掉本題要花費的時間和本題每分鐘會帶來的疲倦值。

輸出描述:

一行包括一個整數,表示處女座今晚訓練會產生的最小疲倦值。
示例1

輸入

6
6 1
4 5
4 3
6 2
8 1
2 6

輸出

86

說明

先做第6個題,增加(1+5+3+2+1)*2= 24 點疲倦值,再做第2個題,增加28點疲倦值,隨後依次是第3,4,1,5道題,增加16,12,6點疲倦值。總共的疲倦值是24 + 28 + 16 + 12 + 6 = 86點。

備註:

2N1052≤N≤105.
2ai4?1062≤ai≤4?106.
1bi1000



貪心,策略是按 每個作業的分鐘疲勞值 排序,具體見代碼。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
struct node{
    LL a,b;
    double d; 
}p[100001];
bool cmp(node x,node y){
    return x.d > y.d;
}
int main()
{
    int n;scanf("%d",&n);
    LL sum = 0;
    LL ans = 0;
    for(int i = 0 ; i < n ; i++){
        scanf("%lld %lld",&p[i].a,&p[i].b);
        sum += p[i].b*1LL;
    }
    for(int i = 0 ; i < n ; i++){
        p[i].d = (p[i].b*1.0)/p[i].a; 
    }
    sort(p,p+n,cmp);
    for(int i = 0 ; i < n ; i ++){
        sum -= p[i].b*1LL;
        ans += sum*p[i].a*1LL;
    }
    cout<<ans*1LL<<endl;
}

E題:處女座和小姐姐

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

既然昨天晚上處女座已經訓練了,明天才要交作業,那今天就是平淡無奇要上課的一天了。

然而處女座也想自己的小姐姐了,可是這節課是老師安排座位,處女座坐在(1,1),而小姐姐坐在(n,m)。他們之間只能通過傳紙條的方式來交流感情。對於處女座而言,他上課不想過度分心,因此並不想傳紙條,只在那裏趁機折千紙鶴。

老師上課喜歡用"開火車"的方式讓大家輪流回答問題,顯然處女座作為(1,1)位,會被第一個叫起來回答,之後老師將依次叫起(2,1),(3,1),.(n,1),(n,2),(n?1,2)?(1,2),?(2,1),(3,1),….(n,1),(n,2),(n?1,2)?(1,2),?的人起來回答問題,每個人回答問題需要1秒。處女座在自己回答完以後會以每秒1個千紙鶴的速度折疊,在小姐姐開始回答問題的時候停止折疊。

處女座想知道,他這節課一共要折多少個千紙鶴?

輸入描述:

輸入文件包含T+1行,第一行包含一個整數T,表示用例組數。

接下來T行,每行包含兩個整數n,m表示小姐姐的位置和教室的大小。

輸出描述:

對於每一組用例,用一行輸出一個整數,表示處女座要折的千紙鶴的個數。
示例1

輸入

1
3 3

輸出

7

備註:

2n,m1,000

根據題目直接算即可,註意奇數行和偶數行最後的拐點問題,即需要把小姐姐的位置分奇偶數考慮。
代碼:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int _;
    for(scanf("%d",&_);_--;){
        LL n,m;
        cin>>n>>m;
        if(m&1)
            cout<<(n*m*1LL-2LL)<<endl;
        else
            cout<<(n*(m-1)*1LL-1LL)<<endl;
    }
}/*
1
3 3
*/

G題:處女座和小姐姐(三)

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述




技術分享圖片
 經過了選號和漫長的等待,處女座終於拿到了給小姐姐定制的手環,小姐姐看到以後直呼666!

處女座其實也挺喜歡6這個數字的,實際上他做手環的時候選取的k=6。所以他對於包含數碼6的數字極其敏感。每次看到像4567這樣的數字的時候他的心就像觸電了一樣,想起了小姐姐。

現在你要給處女座展示一系列數字,你想知道他的內心會激動多少次。對於同一個數字,他最多只會激動一次,即如果這個數是66666,他還是只會激動一次。

輸入描述:

一行包括兩個數字l,r,表示你給處女座展示的數字範圍為[l,r]。

輸出描述:

一行一個整數,表示處女座內心激動的次數。
示例1

輸入

10 20

輸出

1

備註:

0lr1018

思路:看到選取某個滿足條件的數,和那麽大的區間,直接考慮數位DP。dp[i][j]表示,dp[i][j]表示i+1位數,且以j為開頭,不包含6的數的個數。
遞推式則很顯然能得到:dp[i][j] = dp[i][j] + (j == 6? 0: dp[i-1][k]); 即當當前位是6時,不遞推上去,其他數字則遞推到下一個狀態。
不大會的可以先做“不要62”這道題。另外註意範圍是long long。

代碼:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
const int maxn = 20;
LL dp[maxn][maxn];//dp[i][j]表示i+1位數,且以j為開頭,不包含6的數的個數
void init(){
    memset(dp,0,sizeof(dp));
    dp[0][0] = 1LL;
    for(int i = 1 ; i <= 19 ; i ++){
        for(int j = 0 ; j < 10 ;j ++){
            for(int k = 0 ; k < 10 ; k ++){
                if(j != 6){
                    dp[i][j] += dp[i-1][k]*1LL;
                }
            }
        }
    }
}
LL solve(LL x){
    int digit[20];
    int k = 0;
    LL tmp = x;
    while(tmp){
        digit[++k] = tmp%10;
        tmp/=10;
    }
    digit[k+1] = 0;
    LL ans = 0;
    for(int i = k;i > 0; i--){
        for(int j = 0 ; j < digit[i] ; ++j){
            if(j != 6){
                ans += dp[i][j]*1LL;
            }
        }
        if(digit[i] == 6) break;
    }
    return x - ans;  
}
int main()
{
    init();
    LL a,b;
    while(cin>>a>>b) 
    cout<<(solve(b+1LL) - solve(a))*1LL<<endl;
}
/*
0 1000000000000000000
*/

I題:處女座的約會

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

處女座放完了"高利貸",拿到了不少的資金,又可以和小姐姐約會啦!(之前不還是攢錢打比賽的嗎)現在處女座拿到了一份寧波市旅遊地圖決定和小姐姐一起去玩耍。他們來到了動物園,去參觀裏面的動物。但是很不幸的是,他們在遊玩的途中遇到了一只惡龍。

惡龍長有n個頭,但經過了處女座的調教,惡龍變得善良了一些。它的n個頭每個頭要麽仍是邪惡的頭,用“1”表示,要麽已經變得善良,用“0”表示,因而惡龍的n個頭就可以用n位01串來表示。而此時處女座要發揮自己的勇士形象,要把所有的龍頭都變成0000?000000?00完全善良的龍頭。每一次,他可以砍掉龍最右側的一個頭,同時龍會在最左側長出新的一個頭,以保證龍頭數量不變。如果他砍掉的是一個1,即邪惡的頭,他可以決定龍在最左側會長出什麽樣的頭;但如果他砍掉了一個善良的頭,那麽玻璃心的惡龍將會在左側不受控制的長出一個隨機的頭,既可能是善良的頭,也可能是邪惡的頭,而且它總會與處女座作對,盡力的破壞他的計劃。
現在給你一個惡龍頭的初始狀態,即一個01串,請幫助處女座判斷一下,能否在有限步之內讓全部的龍頭都變成善良的龍頭。

輸入描述:

輸入第一行T,表示用例組數。

之後T行,每行一個01串S表示龍頭的初始狀態,“0”表示善良的頭,“1”表示邪惡的頭。

輸出描述:

對於每組數據,處女座能否將全部的龍頭變成善良的頭,可以的話輸出“cnznb”,不可以則輸出“ljcnz”(不含引號)。
示例1

輸入

1
1111

輸出

cnznb

備註:

T1000T≤1000
|S|100|S|≤100
註意,這個問題可能沒有你想的那麽簡單。顯然,處女座必須把一些1變成0,這樣才能讓1的數量減少並消失。但是如果只是簡單的每次把1變成0,最終不見得能取勝。比如,如果龍頭的狀態是101,那麽去掉最右邊的1並選擇在左邊長出一個0,則龍頭會變成010;再把010右邊的0去掉後,如果左邊仍長出一個1,則龍頭又變回了101的狀態,如此反復,將永遠不能得到000。


思路:
看到題目之後以為要用sg函數。手推了一下發現有個規律:如果是全1肯定可以變成全0(因為1可以自己選擇變成0或者1,不需要隨機);
那麽很自然的過渡到幾種情況:
①:最右邊是1,此時砍掉之後我們可以最左邊增加一個1
②:最右邊是0,此時砍掉後最左邊隨機加0或者1,假設是1,情況則同①
③:最右邊是0,此時砍掉後最左邊隨機加0或者1,假設是0,那麽先不管,等到下次再回來的時候進入隨機。

發現只要是,惡龍砍掉後加的頭還是惡龍,則可以把1的比例不斷增加,直到全1。
此時則可全部變成0。
到此,發現無論輸入的是什麽,都能在有限步變成全0.(題目的提示很有誤導性,當然也會帶來啟發,例如句子“
但是如果只是簡單的每次把1變成0,最終不見得能取勝”)暗示可以變1。
代碼:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        string s;
        cin>>s;
        cout<<"cnznb"<<endl;
    }
}

 

牛客寒假算法基礎集訓營3(部分)