牛客練習賽20(ABC)
題意:
我從買奧利奧的事情中想出了一個算法題:假設某個店鋪有N種不同類型的1元奧利奧和M種不同類型的2元奧利奧,而且余量無限,我的錢有k元,我想把k元都用來買奧利奧,且可以買同類型的奧利奧,你能幫我算出有多少種購買方式嗎?設答案為Z,這個數字也許會很大,所以我們只需要輸出Z mod P的值。
分析:
計數問題,可以考慮動態規劃:每個物品可以選無數次,即無窮背包,註意無窮背包的遞推寫法。
?
#include <bits/stdc++.h> using namespace std; const int MAXN = 1005; int N,M,K,P;int d[MAXN]; int main() { int T; scanf("%d",&T); while(T--) { memset(d,0,sizeof(d)); scanf("%d%d%d%d",&N,&M,&K,&P); d[0] = 1; for(int i = 1; i <= N; i++) { for(int k = 1; k <= K; k++) d[k] = (d[k] + d[k-1])%P; } for(int i = 1; i <= M; i++) { for(int k = 2; k <= K; k++) d[k] = (d[k] + d[k-2])%P; } printf("%d\n",d[K] ); } return 0; } ?
B. 麻婆豆腐
題意:
“咳咳...請聽題!我手上有n枚硬幣,第i枚正面朝上的概率是Pi。我現在每個硬幣各拋一次,正面朝上看做1,背面朝上看做0,把所有硬幣得到的數異或起來決定最後得到的數。問:有多少個子集合使得0和1的概率相等?” 不管音無給了怎樣的數,奏都是一分鐘不到就算出來了!不愧是前學生會長啊~ 於是他們就去食堂吃麻婆豆腐了,現在,你也來算一下吧。
分析:
可以說這個題很驚世駭俗了,當一個硬幣的概率是0.5時,它一反轉,所得異或值就會改變,而且概率相等,反之,當他的概率不是0.5時,概率必然不等,答案就轉化為有多少個集合至少含有一個0.5的硬幣,取補集,概率為0.5的硬幣是 ? ?
int main() { int T; scanf("%d",&T); for(int i = 0; i < T; i++) { int n; scanf("%d",&n); int cnt = 0; double p; for(int i = 0; i < n; i++) { scanf("%lf",&p); if(p==0.5) cnt++; } cnt = n - cnt; long long ans = 1,cnts=1; for(int i = 0; i < n; i++) ans<<=1; for(int i = 0; i < cnt; i++) cnts<<=1; cout<<ans-cnts<<endl; ? } return 0; }
C. 尋寶
題意:
這個迷宮由n個房間組成,編號為0到n - 1,每個房間裏都有一顆寶石,房間通過單向通道連接。每個房間裏有兩個門:一個通向第R個房間(R=(a·v2 + b·v + c) mod n),另一個通向迷宮出口,一旦離開迷宮,便會觸發自毀機關,將再也沒有機會繼續收集寶石。現在,她可以在任何地點進入迷宮,沿隧道移動並收集寶石。
分析:
因為每個點,出度均為1,點的數目 ? ,時間復雜度需要 ? 。
那麽圖裏面只有環,和鏈+環,這樣標記遍歷即可。
首先遍歷鏈,發現有環後,從那裏再第二次標記,這樣,環上每個結點都是環的長度。
鏈就相應要短一些。註意,訪問的時候,下面的節點已經訪問過了。
#include <bits/stdc++.h> using namespace std; long long a,b,c,m; long long f(long long v) { return (a*v*v + b*v + c)%m; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld",&a,&b,&c,&m); vector<long long> L(m,-1); for(long long i = 0; i < m; i++) { if(L[i]>=0) continue; long long p = i; long long plen = 0; while(L[p]==-1) { L[p] = -2; plen ++; p = f(p); } if(L[p]>0) { plen+=L[p]; } long long clen = 0; while(L[p]==-2) { L[p] = -3; clen++; p = f(p); } p = i; while(L[p]<0) { if(L[p]==-3) L[p] = clen; if(L[p]==-2) L[p] = plen--; p = f(p); } } cout<<*max_element(L.begin(),L.end())<<endl; } return 0; }
牛客練習賽20(ABC)