牛客网训练2总结
1.求導
分析
求階乘,但是不能簡單的遞歸,這樣會TLE。需要記憶化遞歸,同時為防止數據爆掉,需要邊乘邊取余
ac代碼
#include<iostream>using namespace std;const int maxn=1e9+7; long long n ,result; long long fact(long long n){if(n==0||n==1) return 1;//退出條件long long dp[100001];dp[1]=1;for(int i=2;i<=n;i++)//記憶化dp[i]=dp[i-1]*i%maxn;//計算階乘return dp[n]; } int main(){cin>>n;if(n<0) cout<<0<<endl;else{cout<<fact(n)<<endl; }}2.猜數
鏈接:猜數
來源:牛客網
題目描述
紙上寫了 n 個數字,牛牛在之前改動了幾個數字,他忘了他具體改了些數字了。
但是他記得動之前這些數字的和是 ≥m\ge m≥m 的,求他最少改動幾個數字。
注意:這些數字在改之前和改之后均在 0 ~ 9 之間,且為整數。
輸入描述:
第一行給出 n,m
第二行給出 n 個 0 ~ 9 的整數
輸出描述:
輸出最少改動了幾個數字。(保證答案 \le n≤n)
示例
輸入
輸出
1
對于 50% 數據有 n≤20n\le 20n≤20
對于 100% 數據有n≤106n\le10^{6}n≤106
分析
把最小的數據變成9可以有最少的改動次數。輸入時求和,之后從小到大排序,每次改動最小的數,并且更新和,不滿足累加器+1,直到滿足添加。
ac代碼
3.累乘數字
鏈接:累乘數字
來源:牛客網
題目描述
我們知道將一個大于1的數乘以另一個大于1的數會使乘積大于任意一個乘數。
現在給出兩個數字 n, d,你能否計算將n乘以d次100的結果。
輸入描述:
多組輸入
每組輸入在一行中給出n, d, 1≤n,d≤1001 \le n, d \le 1001≤n,d≤100。
輸出描述:
每組輸入輸出一行代表答案。
示例1
輸入
輸出
500 1100 850000分析
字符讀入,后面補2d個零。
ac代碼
4.解鎖專家
鏈接:解鎖專家
來源:牛客網
文字鎖是這樣描述的,
對于給定的一個n,問存在多少正整數x滿足:
1、x>0;
2、x二進制位的位數不超過n,例如5=101(2),它的二進制位的位數就是3;
3、x的二進制形式,不存在連續的兩個二進制位上的數都是1。例如 3=11(2),則不滿足條件,但是5=101(2) 則滿足條件。
題目大意
給定二進制的位數n(n<=100),求出沒有相鄰的1,并且不為0的組合個數。
比如n=3,可以有001,010,101,100四種
分析
通過找規律,發現dp[i]=dp[i-1]+dp[i-2]+1,打表
| 1 | dp[1]=1 |
| 2 | dp[2]=2 |
| 3 | dp[3]=4 |
| 4 | dp[4]=7 |
| 5 | dp[5]=12 |
| … | … |
| i | dp[i-1]+dp[i-2]+1 |
ac代碼
#include<iostream> using namespace std; const int maxn=433494437; int n; int dp[200];//dp[i]表示i位二進制滿足條件的個數 int main(){dp[1]=1;dp[2]=2;for(int i=3;i<=100;i++)dp[i]=(dp[i-2]+dp[i-1]+1)%maxn;while(cin>>n){cout<<dp[n]<<endl;}}5.答題卡
鏈接:答題卡
來源:牛客網
牛牛即將要參加考試,他學會了填答題卡。
可惜他豎著的答題卡填成了橫著的
好奇的他想知道對于 n 道題,每道題 n 個選項的答題卡 ( n * n 的矩陣 ),滿足橫答題卡和豎答題卡圖形一致的方案數有多少種。
注:每道題只能選擇一個選項,即 n * n 的矩陣中只能涂黑 n 個空。求橫豎對稱的方案數。
數據規模
鏈接:https://ac.nowcoder.com/acm/contest/5769/F
來源:牛客網
對于 50% 的數據有 n≤10n \leq 10n≤10
對于 100% 的數據有 n≤105n\le 10^5n≤105
分析
對于第一個位置,可以分為填或者不填兩種情況。
如果填,則該行該列都不能填(該行不能填是因為每行只能填一個,對稱的話,每列也只能填一個空),于是等價為剩下右下角的(i-1)階方陣,dp[i-1]
如果不填第一個空,在第一行剩余(i-1)個位置找一個有(i-1)種可能,假設是(1,x),則對稱點是(x,1),x行和x列不能再填,其余部分再拼接成(i-2)*(i-2)方陣。即(i-1)*dp[i-2]
于是狀態轉移
dp[i]=dp[i-1]+(i-1)*dp[i-2];//第1個空填了+第1個空沒填有問題代碼,數據爆掉
ll test(ll n){dp[1]=1;dp[2]=2;for(ll i=3;i<=n;i++)dp[i]=dp[i-1]+(i-1)*dp[i-2];return dp[n]%mod;}
應該在每一次dp的位置都進行取模運算
完全AC代碼
記得每次計算都進行mod,中間過程需要,最后的結果也需要dp[i]=(dp[i-1]%mod+(i-1)%mod*dp[i-2]%mod)%mod;
#include<iostream> #include<string> using namespace std; const int maxn=1e5+10; const int mod=1e9+7; typedef long long ll; ll n, dp[maxn];ll test(ll n){dp[1]=1;dp[2]=2;for(ll i=3;i<=n;i++)dp[i]=(dp[i-1]%mod+(i-1)%mod*dp[i-2]%mod)%mod;return dp[n];}int main(){cin>>n;cout<<test(n)<<endl; }6.參賽
能不能組成參賽隊,
題目大意
群里n個人,icpc賽事3個人一隊,天梯賽事10個人一隊,每個隊配備一名教練,教練可以當多個參賽隊的教練,隊員可以參與不同的隊伍,但是隊員不能參與同一賽事的不同隊伍。問能否成功組成隊伍。
分析
錯誤思考,讓隊伍足夠多,教練足夠少,只要取余不為零說明可以組成。
錯誤代碼
#include<iostream> #include<cstdio>using namespace std;int n; int main(){while(scanf("%d",&n)!=EOF){if(n<=3) cout<<"No"<<endl;else if(n>3&&n<=10){if(n%3) cout<<"First"<<endl;else cout<<"No"<<endl;}else{if(n%3&&n%10) cout<<"All"<<endl;else if(n%3&&n%10==0) cout<<"First"<<endl;else if(n%3==0&&n%10) cout<<"Second"<<endl;else cout<<"No"<<endl;}}return 0;}錯誤代碼結果
正確思考
確實是貪心:讓參賽隊足夠多,教練足夠少但不為零。
分開獨立完成,
對于icpc賽事,
如果對3取余不為0,并且參賽隊個數大于等于教練數,則可以組隊成功。如果對3取余為0,這個時候要看能不能拆開一支隊伍,使得該隊伍里面的人成為教練,這個時候要求隊伍數≥教練數(隊伍數-1≥3)才可以。
比如5個人,5/3==1……2,隊伍數少于教練數,組不成隊伍。
比如9個人,9%3==3,沒有余數,也就是說沒有教練,這個時候考慮,能不能拆開1只參賽隊,變成2支隊伍,3名教練,結果卻發現教練數>隊伍數,則不行。所以9個人組不成隊伍。
再比如12個人,12%3= =4,也沒有教練,考慮拆開一只參賽隊,變成3支隊伍,3個教練,隊伍數≥教練數,這個時候可以組成icpc隊伍。
對于天梯賽事,同理
如果對10取余不為0,并且參賽隊個數大于等于教練數,則可以組隊成功。
如果對10取余為0,這個時候要看能不能拆開一支隊伍,使得該隊伍里面的人成為教練,這個時候要求隊伍數≥教練數才可以。
ac代碼
#include<iostream> #include<cstdio>using namespace std;int n; int main(){while(scanf("%d",&n)!=EOF){bool flag1=false,flag2=false;//icpc賽事int a=n/3,b=n%3;//分別是參賽隊伍數和教練數if(b!=0 &&a>=b) flag1=true;//教練不為0,參賽隊≥教練//教練為0,拆開一只隊伍之后參賽隊≥教練else if(b==0&&a-1>=3) flag1=true;else flag1=false;//天梯賽事int c=n/10,d=n%10;//分別是參賽隊伍和教練數if(d!=0 &&c>=d) flag2=true;//教練為0,拆開一只隊伍之后參賽隊≥教練else if(d==0&& c-1>=10) flag2=true;else flag2=false;if(flag1&&flag2) cout<<"All"<<endl;else if(flag1) cout<<"First"<<endl;else if(flag2) cout<<"Second"<<endl;else cout<<"No"<<endl;}return 0;}總結
- 上一篇: c++编译器pointer to a f
- 下一篇: 螨虫怎么预防和治疗 有效的螨虫防治方法?