GDUT2016年ACM新生杯初賽題解
Problem A: 貪吃的zhazhahe
Description
Zhazhahe很喜歡吃燒餅,但是要做好一塊燒餅,要把兩面都弄熱,如果一次只能弄一個,zhazhahe一定會等得不耐煩,幸好現在有一個大的平底鍋,一次可以同時放入k個燒餅,一分鐘只能做好一面。而現在有n個燒餅,至少需要多少分鐘才能全部做好呢?Input
輸入資料組數為T(T<=100),每組資料輸入n和k,中間以空格隔開,其中1<=k,n<=1,000,000,000;Output
對於每個測試樣例,輸出全部做好所需的最少分鐘數。Sample Input
2 1 1 3 2Sample Output
HINT
/* 分析:首先我們知道n個餅總的需要烤的面數是2*n,每次我們最多可以烤k面, 所以烤的最小次數是2*n/k(整除時),或者2*n/k+1(不整除時,餘數部分需要整體烤一次) */ #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; int main() { int t;cin>>t; while(t--){ int n,k; scanf("%d%d",&n,&k); if(n<=k){ printf("%d\n",2); continue; } if(2*n%k!=0) printf("%d\n",2*n/k+1); else printf("%d\n",2*n/k); } return 0; } /************************************************************** Problem: 1196 User: MDZZhhh Language: C++ Result: Accepted Time:0 ms Memory:1696 kb ****************************************************************/
Problem B: 簽到題
Description
某一天,北原春希、小木曾雪菜和冬馬和紗分享幸福度。他們希望三人能平等獲得這份幸福,否則他們就會各奔東西。於是叫你來判斷他們能否三個人快樂的玩耍下去。Input
輸入資料為T組(T <= 100),每組資料讀入一個幸福度n。(1<=n的位數<=500)Output
對於每個測試例項,如果三人能平等獲得幸福,則輸出“Three people are the most stable”,否則輸出“Why would it be like this”。雙引號不用輸出。Sample Input
3 111111111Sample Output
Three people are the most stable Three people are the most stable Why would it be like thisHINT
/*
分析:把每一位加起來判斷是否能夠整除3即可。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
char s[maxn];
int main()
{
int t;cin>>t;
while(t--){
scanf("%s",s);
int len=strlen(s);
int sum=0;
for(int i=0;i<len;i++){
sum+=s[i]-'0';
}
if(sum%3)puts("Why would it be like this");
else puts("Three people are the most stable");
}
return 0;
}
/**************************************************************
Problem: 1197
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1696 kb
****************************************************************/
Problem C: 算罰時
Description
某次ACM比賽中你一次AC了全部8道題目,給出你AC每道題的時間,算出自己的罰時。Input
輸入資料為T組(T <= 100),每組資料讀入8個時間,時間格式是HH:MM。每道題目的罰時為AC所用的分鐘數。Output
每組輸出8道題的罰時之和。Sample Input
3 00:00 00:00 00:00 00:00 00:00 00:00 00:00 00:00 05:00 05:00 05:00 05:00 05:00 05:00 05:00 05:00 00:30 01:00 01:30 02:00 02:30 03:00 03:30 04:00Sample Output
0 2400 1080/*
分析:按照題意寫就行了
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
int main()
{
int t;cin>>t;
while(t--){
int a,b,sum=0;
for(int i=0;i<8;i++){
scanf("%d:%d",&a,&b);
sum+=a*60+b;
}
printf("%d\n",sum);
}
return 0;
}
/**************************************************************
Problem: 1198
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1696 kb
****************************************************************/
Problem D: 有趣的遊戲
Description
有個小師妹找zhazhahe玩遊戲。他們有一堆n個珠子,每人輪流拿走若干個,輪到誰的回合拿不了珠子就算輸。給出一個n,每次能拿走的珠子數量在區間[l,r]內(如果剩餘珠子不足就不能拿,判輸),小師妹先開始拿。假設小師妹和zhazhahe都非常聰明,會採取最優策略,問誰會贏得遊戲?
Input
有多組樣例,第一行輸入一個樣例數T(0<T<=1000)
每個樣例只有一行,三個正整數n,l,r (0<n<=1000) (0<l<=r<=1000)
Output
每個樣例只有一行,如果小師妹贏了輸出“Win”,輸了就輸出“Lose”。
Sample Input
3 4 1 4 7 2 6 10 3 6Sample Output
Win Win LoseHINT
/*
型別:博弈
分析:這種型別題的基本思路是找到一種恆定不變的方式,使得對方無論怎麼拿,你都能找到對應要拿的數量
舉個例子,假如n=22,取的區間為[1,2],那麼小師妹第一次拿走1個,
使得剩下的數量21,是區間左右端點之和的倍數,即3的倍數.
那麼無論對方怎麼拿,我們都能維持剩下來的數量是3的倍數的狀態不變,比如他拿1個,你就拿2個,或者他拿2個,你就拿1個
始終保持他能拿,我必能拿的狀態,那麼只要判斷初始情況,我就知道我能不能穩贏
回顧剛剛的拿法,我們很容易推出一個方式判斷第一個人應該如何拿,即餘數=n%(L+R)
1.假設這個餘數落在[L,R]裡面,那麼小師妹第一次把餘數全抓走,剩下的是(L+R)的倍數,我們知道,小師妹穩贏
2.假設這個餘數為L-k (0<k<=L)裡面,那麼因為只能抓[L,R]個珠子,小師妹動不了餘數這個數目,她只能先動(L+R)裡面合法的某些數目,那麼第二個人能對應著拿掉小師妹在(L+R)裡面剩下的數目,情況變成小師妹穩輸
3.假設這個餘數落在R+L-k (0<k<L)裡面,那麼小師妹第一次拿走R個,剩下的數目為L-k即把第二種狀態丟給對方,小師妹穩贏
所以題目可以解決.
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 505;
int main()
{
int t;cin>>t;
while(t--){
int n,l,r;
scanf("%d%d%d",&n,&l,&r);
if(n%(l+r)<l)puts("Lose");
else puts("Win");
}
return 0;
}
/**************************************************************
Problem: 1199
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1696 kb
****************************************************************/
Problem E: 套套套
Description
矩形A能與矩形B不接觸的放在矩形B裡就稱為矩形A能巢狀進矩形B。
給你n個矩形,編寫程式,判斷它們能否互不接觸巢狀n層。
如:有2 * 2 , 4*5,3*4 三個矩形。
方案一巢狀非法,但是方案二合法(巢狀順序任意),所以2*2,3*4,4*5滿足條件
Input
第一行一個整數t(t < 15 ),表示有t組資料。 每組資料第一行一個整數n(n < 10000),矩形的個數,接下去的n行,每行兩個正整數x和y(由空格分開),第i行表示第i個矩形的長為x和寬為y。(0 < y <= x < 100000 )
Output
每組資料輸出一行,矩形能完成巢狀則輸出“Yes”,否則輸出“No”。(不包含雙引號)
Sample Input
2 3 2 2 4 3 5 4 2 2 1 3 1Sample Output
Yes NoHINT
/*
分析:因為題目限制了n個矩形要達到n層巢狀,所以對於n個矩形能否滿足條件,
我們只需要先對所有矩形的面積從小到大排序,再判斷相鄰兩個矩形能否嵌入即可
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
struct rt{
ll x,y,s;
};
rt a[maxn];
bool cmp(const rt&a,const rt&b){
return a.s<b.s;
}
int main()
{
int t;cin>>t;
while(t--){
int n;scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld%lld",&a[i].x,&a[i].y);
a[i].s=a[i].x*a[i].y;
}
sort(a,a+n,cmp);
int flag=1;
for(int i=1;i<n;i++){
if((a[i].x>a[i-1].x&&a[i].y>a[i-1].y)||(a[i].x>a[i-1].y&&a[i].y>a[i-1].x))continue;
else{
flag=0;break;
}
}
if(flag)puts("Yes");
else puts("No");
}
return 0;
}
/**************************************************************
Problem: 1200
User: MDZZhhh
Language: C++
Result: Accepted
Time:8 ms
Memory:1940 kb
****************************************************************/
Problem F: 吃豆豆
Description
在二進位制下,十進位制下的10寫成1010,12可以寫成1100。這個時候貪吃的Shadow把一些十進位制下的數看成了二進位制,並且把二進位制中每一個1都看成了一顆豆豆,Shadow把這些十進位制下的數字叫做豆數,Shadow想知道,他在每一個豆數中可以吃到多少顆豆豆。Input
多組資料,對於每一組資料,有一個整數 n,代表豆數的值。最後以 -1結束輸入。其中 0 <= n <= 1e18.Output
對於每組資料輸出一個整數,代表可以吃到的豆子數。Sample Input
1012 -1Sample Output
22HINT
/*
分析:判斷一個數的二進位制裡面有幾個1,不斷對2取模和除2,看有幾個滿足即可
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
int main()
{
//int t;cin>>t;
ll n;
while(~scanf("%lld",&n)&&n!=-1){
int sum=0;
while(n){
sum+=n%2;
n/=2;
}
printf("%d\n",sum);
}
return 0;
}
/**************************************************************
Problem: 1201
User: MDZZhhh
Language: C++
Result: Accepted
Time:8 ms
Memory:1696 kb
****************************************************************/
Problem G: Pigofzhou和他的那麼多個學妹
Description
男神pigofzhou在開學還沒多久就基本上與16級幾乎所有的師妹打成了一片,不過由於男生pigofzhou認識的師妹太多了,但是又怕忘了,於是就拿個本子記錄下來,有一天他忽然想看一下這本本子有多少面,但是畢竟是pigofzhou怎麼可能直接去數本子有多少面呢,於是對於每一頁的頁碼都用鍵盤敲到電腦上,然後數自己敲了幾次鍵盤,從而計算出本子有多少面,可以吧,這很pigofzhou,例如頁碼為1~9頁,每頁敲一下鍵盤,頁碼為10~99頁,每頁敲2下鍵盤,頁碼為100~999頁,每頁敲三下,以此類推。
Input
輸入一個正整數t(0<t<3000)表示樣例組數,每組樣例輸入一個正整數n(0<n<1e12),表示敲了n下鍵盤。
Output
輸出一個正整數表示這本本子有多少面
Sample Input
5 9 11 15 23 39Sample Output
9 10 12 16 24HINT
雖然廣工沒那麼多女生,但是資料並不小
/*
分析:先預處理出第9、99、999、9999...頁敲擊鍵盤的次數,得到邊界值,
然後每次用邊界值查詢到n屬於那個區域,再用n減去下界的次數得到從該區域第一個頁數到當前頁數的總敲擊次數
再用敲擊次數求出該頁數是在當前區域的第幾個,再-1+10^數字的位數,就是答案
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10000+5;
ll a[15],p[15];//a儲存邊界值,p[i]表示10^(i-1)
int main()
{
a[1]=9;p[1]=1;
for(ll i=2,t=10;i<=13;i++,t*=10){
a[i]=i*9*t+a[i-1];
p[i]=t;
}
int t;cin>>t;
while(t--){
ll n;scanf("%lld",&n);
for(int i=1;i<=13;i++){
if(a[i]>n){
printf("%lld\n",(n-a[i-1])/i-1+p[i]);
break;
}
}
}
return 0;
}
/**************************************************************
Problem: 1202
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1696 kb
****************************************************************/
Problem H: 神奇的清華大大的神奇魔法
Description
清華大大很喜歡字串,因為在他眼中,字串有關的題目都可以輕鬆解決。 但是清華大大不喜歡不是迴文串的字串,因為如果一個字串是迴文串,意味著清華大大隻讀一半的字串就可以了。 迴文串是前後讀結果相同的字串,例如"p”, "abba"是迴文串,而“ac”,“yt”則不是。 如果遇到非迴文串字元,神奇的清華大大就會施展神奇的魔法,每次他可以消耗1個魔法值將該字串中的一個字母變成另一個字母,或者消耗0個魔法值改變該字串中各個字母的順序。 現在有一個字串(只含小寫字母),請你告訴清華大大該如何做才能施展儘可能少的魔法值使它變成迴文串。Input
第一行為T,有T個樣例。小於50。 接下來每行含有一個字串,每個字串長度小於200000。Output
每行輸出消耗最少魔法值所產生的迴文字串, 如果有多個結果,輸出字典序最小的結果Sample Input
2 aabc aabcdSample Output
abba abcbaHINT
/*
型別:貪心+模擬
分析:先記錄26個字母的出現次數num[],若num[i]為奇數,且只有一個字母,那麼可以直接輸出
若存在多個num[i]為奇數
這時分兩種情況:
1.需要把其它字母改為當前字母;
2.把該字母改為其它字母。
為了得到最小字典序,我們貪心的選擇將字典序大的字母改為字典序小的字母,按照這樣的思維模擬下去。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 200000+5;
char s[maxn];
int a[30],n;
void print(){
int flag=-1;
for(int i=0;i<26;i++){
if(a[i]%2)flag=i;
}
if(flag==-1){
for(int i=0;i<26;i++){
int len=a[i]/2;
for(int j=0;j<len;j++){
printf("%c",i+'a');
}
a[i]-=len;
}
for(int i=25;i>=0;i--){
for(int j=0;j<a[i];j++){
printf("%c",i+'a');
}
}
puts("");
}
else{
int cnt=0;
for(int i=0;i<26;i++){
int len=a[i]/2;
for(int j=0;j<len;j++){
printf("%c",i+'a');
cnt++;
if(cnt==n/2){
printf("%c",flag+'a');
a[flag]--;
}
}
a[i]-=len;
}
for(int i=25;i>=0;i--){
for(int j=0;j<a[i];j++){
printf("%c",i+'a');
}
}
puts("");
}
}
int main()
{
int t;cin>>t;
while(t--)
{
memset(a,0,sizeof(a));
scanf("%s",s);
int len=strlen(s);
n=len;
for(int i=0;i<len;i++){
a[s[i]-'a']++;
}
int flag=0;
for(int i=0;i<26;i++){
flag+=a[i]%2;
}
if(flag<=1)print();
else{
int k=26;
while(k--){
//flag=0;
int r=-1,l=-1;
for(int i=25;i>=0;i--){
if(a[i]%2){
if(r==-1){
r=i;
break;
}
}
}
for(int i=0;i<25;i++){
if(a[i]%2&&l==-1){
l=i;
break;
}
}
if(l!=r){
a[r]--;
a[l]++;
}
}
print();
}
}
return 0;
}
/**************************************************************
Problem: 1203
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1896 kb
****************************************************************/
Problem I: 神槍手TMK
Description
TMK十分喜歡打CS,據說GDUTACM新生杯的一等獎的獎品的星際CS的真人CS遊戲團體券,他毅然報了名。 在新生杯的初賽上,TMK被一道題卡住了,然後TMK居然。。。。。睡著了,他夢做了一個很長的夢,他夢見了自己進入了宇宙空間,忽然一班外星人向TMK襲來,TMK在用聰明的頭腦打敗了一個外星人後,成功的奪得了外星人的一把槍,TMK是個神槍手,他每次開槍都能把兩個外星人幹掉。 新生杯結束後,yfq搖醒了TMK,TMK雖然醒了,但他還在回味之前的夢,他想知道自己幹掉了多少個外星人,但他記不清了,他只記得自己開了多少次槍。TMK很不開心,於是yfq想幫幫他算一下他幹掉了多少外星人。Input
題目包含多組資料 對於每一組資料,輸入有一個數字n(-10000<=n<=10000),表示tmk一共開了多少次槍。Output
對於每組資料,輸出一行,如果不能可能有這種情況,那麼肯定是tmk記錯了,輸出”impossble”(不帶引號),否則輸出有一個數字x,表示tmk一共幹掉了多少外星人Sample Input
3260-1Sample Output
75131impossbleHINT
/*
分析:直接寫把
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 200000+5;
int main()
{
//int t;cin>>t;
int n;
while(~scanf("%d",&n)){
if(n<0)puts("impossble");
else printf("%d\n",2*n+1);
}
return 0;
}
/**************************************************************
Problem: 1204
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:1696 kb
****************************************************************/
Problem J: 神龍的煩惱
Description
冰法師zz因為苦修寒冰魔法而耽誤了找女朋友的大事,於是他集齊了7顆龍珠,召喚出了神龍。 神龍:說出你的願望吧。 zz:我想要一個漂亮又聞名世界,會各種姿勢而且絕不會跟我鬧彆扭的妹子做我女朋友。 神龍:這好辦。 於是乎,一個芭蕾娃娃人偶從天而降,神龍消失在天際。 最近太多宅男向神龍許願要女朋友了,這要讓神龍準備多少個芭比娃娃啊。神龍累了,於是他找到了你,希望你幫忙算一它購置m個芭比娃娃的費用。現有n個供貨商,第i(1<=i<=n)個供貨存芭比娃娃量amount[i],單價cost[i]。由於向神龍許願要錢的人也很多,所以神龍希望花費金額數最少,請你告訴它最少需要用多少錢買芭比娃娃。 若供貨商無法提供出m個芭比娃娃,則輸出-1。Input
第一行有兩個整數n,m(1<=n<=10^6,m<=10^8),分別代表供貨商數量和神龍要買的芭比娃娃數量。 第二行到第n+1行均有兩個整數amount[i],cost[i](1<=amount[i],cost[i]<=10^6)分別代表第i個供貨商所存芭比娃娃數量和芭比娃娃的單價.Output
僅有一個整數ans,代表神龍最少花費金額,或者是-1,代表買不到m個芭比娃娃。Sample Input
5 201 14 5010 64 205 8Sample Output
181HINT
/*
分析:價格從小到大買就行了
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
struct babi{
ll num,val;
};
babi a[maxn];
bool cmp(const babi&a,const babi&b){
return a.val<b.val;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
ll sum=0;
for(int i=0;i<n;i++){
scanf("%d%d",&a[i].num,&a[i].val);
sum+=a[i].num;
}
if(sum<m)puts("-1");
else{
sort(a,a+n,cmp);
sum=0;
for(int i=0;i<n;i++){
if(a[i].num<m){
sum+=a[i].val*a[i].num;
m-=a[i].num;
}
else{
sum+=a[i].val*m;
break;
}
}
printf("%lld\n",sum);
}
return 0;
}
/**************************************************************
Problem: 1205
User: MDZZhhh
Language: C++
Result: Accepted
Time:0 ms
Memory:0 kb
****************************************************************/