一篇遲到的題解,本以為大家興趣不大,但是有同學問了,本人覺得還是應該寫一下。
T醬和他的數學題
要求判斷末尾有多少個0
我們分析一下就可以知道0只能是來自2 和 5 的乘積。
對於每一個數字我們只需要去判斷可以分解出多少個2和5就可以,其中5的出現次數一定會小於2的出現次數。
由於是階乘的階乘
所以我們只需要暴力一遍,維護5出現次數的前綴和的前綴和就可以了
1 #include <stdio.h> 2 int cal(int x) 3 { 4 int res = 0; 5 while(x) 6 { 7 if(x%5) break; 8 x /= 5; 9 res++; 10 } 11 return res; 12 } 13 int main() 14 { 15 long long res, tmp; 16 int n; 17 while(scanf("%d", &n) != EOF) 18 { 19 res = tmp = 0; 20 for(int i = 1; i <= n; i++) 21 { 22 tmp += cal(i); 23 res += tmp; 24 } 25 printf("%lld\n", res); 26 } 27 }
Vic和騎士
自己手推一下 n = 4 和n = 5的情況, 就會發現規律,只要RB交錯排列就可以
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 7 int main() 8 { 9 int T, n, ca = 0; 10 while(scanf("%d", &n) != EOF) 11 { 12 for(int i = 1; i <= n; i++) 13 { 14 if(i%2) 15 for(int j = 1; j <= n; j++) 16 if(j%2) putchar('B'); 17 else putchar('R'); 18 if(i%2==0) 19 for(int j = 1; j <= n; j++) 20 if(j%2) putchar('R'); 21 else putchar('B'); 22 23 putchar('\n'); 24 } 25 putchar('\n'); 26 } 27 28 }
Vic與水題
根據題目輸出就可以, 但是我們提交的輸出樣例顯示有點問題,在題面里也說明了
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int T, n, flag; 6 cout<<"#include<stdio.h>"<<endl; 7 cout<<"int main()"<<endl; 8 cout<<"{"<<endl; 9 cout<<"int n;"<<endl; 10 cout<<"n = 10;"<<endl; 11 cout<<"printf(\"%d\", n);"<<endl; 12 cout<<"return 0;"<<endl; 13 cout<<"}"; 14 }
保護牛奶
對於這一題,我們可以發現,牛奶被放成了一圈,並且只能取連續的。
貪心策略是利用圓的對稱性來反制對手,所以只有當數量為1 或 2 或 3 時, 先手才贏的機會
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int main() 5 { 6 int T, n, flag; 7 while(scanf("%d", &T) != EOF) 8 { 9 while(T--) 10 { 11 scanf("%d", &n); 12 if(n<=3&&n>=1) cout<<"milk will die!!!"<<endl; 13 else cout<<"milk is alive!!!"<<endl; 14 } 15 16 } 17 18 }
當老板
這個題目是一個二分題,但是相對於傳統的二分,我們需要計算上界或者下界來保證二分的順利進行.
講一下二分的思路,主要是check比較難
對於check的值 我們假設是X,每一個員工的可接受的工資是[Li, Ri]
那么對於Li>X 的員工只能是讓他排在中位數的右邊
對於Ri<X的員工只能是讓他排在中位數的左邊
然后剩下的我們進行最優分配,如果左邊此時還沒達到要求人數的一半,那么應該補足左邊,這些人發放最小工資,右邊的人則是發放X的工資。最后判讀這樣的分配下花費是否夠用可以。
具體看代碼吧
1 #include <stdio.h> 2 #include <cstring> 3 #include <vector> 4 #include <set> 5 #include <algorithm> 6 using namespace std; 7 struct node 8 { 9 int l, r; 10 bool operator < (struct node a) 11 { 12 return l < a.l; 13 } 14 }a[200009]; 15 typedef long long ll; 16 int T, n, l, r, mid; 17 ll sum; 18 bool check(int x) 19 { 20 vector <struct node> ve; 21 ve.clear(); 22 int num = 0; 23 ll res = 0; 24 for(int i = 1; i <= n; i++) 25 if(a[i].r<x) 26 { 27 res += a[i].l; 28 num++; 29 } 30 else if(a[i].l>x) 31 { 32 res += a[i].l; 33 }else ve.push_back(a[i]); 34 35 if(num>=n/2+1) return false; 36 37 int size = ve.size(); 38 39 for(int i = 0; i < size; i++) 40 if(num<n/2) 41 { 42 res += ve[i].l; 43 num++; 44 }else res += x; 45 46 return res <= sum; 47 } 48 49 int main() 50 { 51 scanf("%d", &T); 52 while(T--) 53 { 54 scanf("%d %lld", &n, &sum); 55 for(int i = 1; i <= n; i++) 56 scanf("%d %d", &a[i].l, &a[i].r); 57 58 r = 1e9; 59 60 sort(a+1, a+1+n); 61 l = a[n/2+1].l; 62 // printf("%d %d\n", l, r); 63 while(l<=r) 64 { 65 mid = (l+r) / 2; 66 if(check(mid)) 67 { 68 if(!check(mid+1)) break; 69 l = mid+1; 70 }else r = mid - 1; 71 } 72 73 printf("%d\n", mid); 74 } 75 }
滴答滴答
這是一個暴力模擬的題目,具體的只需要按題意敲就可以,但是比較難處理的是涉及到了大數,我們用數組模擬一下就可以了,考慮到新生賽的難度,所以還是比較好處理的
1 #include <stdio.h> 2 #include <cstring> 3 #include <string.h> 4 const int N = 2e5+10; 5 char s[N]; 6 int res[N]; 7 int main() 8 { 9 int T, len, pos, num, flag; 10 scanf("%d", &T); 11 while(T--) 12 { 13 scanf("%s", s+1); 14 len = strlen(s+1); 15 num = pos = 0; 16 s[len+1] = '*'; 17 for(int i = 1; i <= len;) 18 { 19 if(s[i]=='d'&&s[i+1]=='a') 20 { 21 flag = 0; 22 i = i + 2; 23 for(int j = 1; j <= 3 && i <= len; i++, j++) 24 if(s[i]<='9'&&s[i]>='0') 25 { 26 res[++pos] = s[i] - '0'; 27 flag = 1; 28 } 29 if(flag) num++; 30 }else if(s[i]=='d'&&s[i+1]=='i') 31 { 32 flag = 0; 33 i = i + 2; 34 for(int j = 1; j <= 1 && i <= len; i++, j++) 35 if(s[i]<='9'&&s[i]>='0') 36 { 37 res[++pos] = s[i] - '0'; 38 flag = 1; 39 } 40 if(flag) num++; 41 }else i++; 42 } 43 res[pos] += num; 44 for(int i = pos; i >= 1; i--) 45 { 46 res[i-1] += res[i] / 10; 47 res[i] %= 10; 48 } 49 flag = 0; 50 for(int i = 0; i <= pos; i++) 51 { 52 if(res[i]) flag = 1; 53 if(flag) printf("%d", res[i]); 54 } 55 if(flag) printf("\n"); 56 else printf("0\n"); 57 } 58 }
取石子游戲
這是一個大三學長出的防AK題,只要了解SG函數,那么恭喜你,你離AC只有半步之遙了,由於SG函數的時間復雜度是N^2 , 所以肯定要優化,其實我們觀察SG函數可以直接得出一個規律,然后這題就AC了。
1 #include <stdio.h> 2 int cal(int x) 3 { 4 for(int i = 0; ; i++) 5 if((1<<i) > x) return i % 3; 6 7 } 8 int main() 9 { 10 int T, n, x, res; 11 scanf("%d", &T); 12 while(T--) 13 { 14 scanf("%d", &n); res = 0; 15 for(int i = 1; i <= n; i++) 16 { 17 scanf("%d", &x); 18 res ^= cal(x); 19 } 20 if(res) printf("first\n"); 21 else printf("second\n"); 22 } 23 }
題目夠簡單嗎
簽到題,讀入然后判斷數組里面有沒有1就可以了
1 #include <stdio.h> 2 int main() 3 { 4 int T, n, flag; 5 while(scanf("%d", &T) != EOF) 6 { 7 while(T--) 8 { 9 scanf("%d", &n); 10 flag = 0; 11 int x; 12 for(int i = 1; i <= n; i++) 13 { 14 scanf("%d", &x); 15 if(x) flag = 1; 16 } 17 if(flag) printf("hard\n"); 18 else printf("easy\n"); 19 } 20 21 } 22 }
推恩令
又是來自大三學長的防Ak題,總的思想是二分。
首先我們對題目分析后,我們可以將題目轉化為有一個全為0的數列,第i我們可以把數列連續顏色的地方變成i然后問我們有多少種方法可以讓原始數列變成輸入的數列。
1 #include <stdio.h> 2 typedef long long ll; 3 ll ans[509][509]; 4 const ll MOD = 292929; 5 int a[509]; 6 void init(int n) 7 { 8 for(int i = 1; i <= n; i++) 9 for(int j = i; j <= n; j++) 10 ans[i][j] = -1; 11 } 12 ll dfs(int l, int r) 13 { 14 if(l>r) return 1; 15 if(ans[l][r]!=-1) return ans[l][r]; 16 ll lans = 0, rans = 0; 17 int pos = l, minn = a[l]; 18 for(int i = l+1; i <= r; i++) 19 if(a[i] < minn) 20 { 21 minn = a[i]; pos = i; 22 } 23 for(int i = l; i <= pos; i++) 24 lans = (lans + dfs(l,i-1) * dfs(i, pos-1) % MOD) % MOD; 25 26 for(int i = pos+1; i <= r+1; i++) 27 rans = (rans + dfs(pos+1, i-1) * dfs(i, r) % MOD) % MOD; 28 29 // printf("%d %d --- %lld %lld\n", l, r, lans * rans + 1); 30 return ans[l][r] = lans * rans % MOD; 31 } 32 int main() 33 { 34 int T, n; 35 scanf("%d", &T); 36 while(T--) 37 { 38 scanf("%d", &n); 39 init(n); 40 for(int i = 1; i <= n; i++) scanf("%d", a+i); 41 printf("%lld\n", dfs(1, n)); 42 } 43 }
五等分的ACM
題意模擬就可以了
1 #include <stdio.h> 2 int cal(int n) 3 { 4 int res = 0; 5 while(n) 6 { 7 int tmp = n % 10; 8 res += tmp * tmp * tmp * tmp * tmp; 9 n /= 10; 10 } 11 return res; 12 } 13 int main() 14 { 15 int T, n; 16 scanf("%d", &T); 17 while(T--) 18 { 19 scanf("%d", &n); 20 if(n==cal(n)) printf("YES\n"); 21 else printf("NO\n"); 22 } 23 }
找找zyh
分析幾個樣例
我們定義numz , numy , numh 為以z y h結尾的前綴的當前出現次數
那么最終的答案就是numh
轉移方程也很好理解, 分別是
當當前字符為 z 時 Numz++;
當當前字符為 y 時 numy += numz
當當前字符為 h 時 numh += numy
字符判斷

對於這三個樣例 我們可以觀察到如果用塗色法去塗這幾個字母,A需要兩次, B需要三次, C需要一次 (需要全部塗滿)。
塗色法可以用dfs處理
需要特殊處理的是,在讀入后要在周圍添一圈留白,不然可能出現留白需要塗多次的情況,這個我們可以在讀入的時候就預留出空間。
1 #include <stdio.h> 2 #include <cstring> 3 char s[50][50] = {0}; 4 int move[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; 5 void dfs(int x, int y) 6 { 7 s[x][y] = '*'; 8 int tx, ty; 9 for(int i = 0; i < 4; i++) 10 { 11 tx = x + move[i][0]; 12 ty = y + move[i][1]; 13 if(tx<0 || tx>49 || ty<0 || ty>49) continue; 14 if(s[tx][ty]=='*') continue; 15 // printf("goto %d %d\n", tx, ty); 16 dfs(tx, ty); 17 } 18 } 19 int main() 20 { 21 22 int time = 0, n; 23 while(gets(s[1]) != NULL) 24 { 25 time = 0; 26 if(strlen(s[1]) == 0) continue; 27 n = 1; 28 for(int i = 2; ; i++) 29 { 30 gets(s[i]); 31 if(strlen(s[i])==0) break; 32 n++; 33 } 34 35 // for(int i = 1; i <= n; i++) 36 // puts(s[i]); 37 38 for(int i = 0; i <= 49; i++) 39 for(int j = 0; j <= 49; j++) 40 { 41 if(s[i][j]!='*') 42 { 43 dfs(i, j); 44 time++; 45 } 46 } 47 48 // printf("%d\n", time); 49 50 if(time==1) printf("C\n"); 51 else if(time==2) printf("A\n"); 52 else printf("B\n"); 53 54 memset(s, 0, sizeof(s)); 55 } 56 return 0; 57 }
足球經理
利用二維數組讀入后,我們對於每一個隊暴力模擬,計算分數就可以了
計算完分數判斷最大值,然后看有沒有兩個隊分數一樣就可以
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 int res[120][120]; 6 struct node 7 { 8 int score, id; 9 bool operator < (struct node a) 10 { 11 return score > a.score; 12 } 13 }a[120]; 14 15 int main() 16 { 17 int T, n; 18 while(scanf("%d", &T) != EOF) 19 { 20 while(T--) 21 { 22 scanf("%d", &n); 23 for(int i = 1; i <= n; i++) 24 for(int j = 1; j <= n; j++) 25 scanf("%d", &res[i][j]); 26 27 for(int i = 1; i <= n; i++) 28 { 29 a[i].id = i; 30 a[i].score = 0; 31 for(int j = 1; j <= n; j++) 32 { 33 if(i==j) continue; 34 if(res[i][j] > res[j][i]) a[i].score += 3; 35 else if(res[i][j]==res[j][i]) a[i].score += 1; 36 } 37 } 38 a[n+1].score = -1; 39 sort(a+1, a+1+n); 40 if(a[1].score != a[2].score) printf("%d\n", a[1].id); 41 else printf("yep!\n"); 42 } 43 } 44 45 }
