連接:https://codeforces.com/contest/1099html
題意:有一個雪球從山頂滾落,山坡上有兩塊石頭,每秒鐘會一次發生三件事:一、雪球增重,數值爲當前高度;二、若是當前高度有一塊石頭,則會撞到石頭,損失跟石頭一樣重的重量;三、往下移動一米。此外,若雪球的重量若是變爲負數,則自動變成零。雪球會在高度爲零處中止滾動,問中止滾動時雪球重量。c++
題解:模擬水題。spa
AC代碼:code
#include<bits/stdc++.h> using namespace std; int w,h; int u[2],d[2]; int main() { cin>>w>>h; cin>>u[0]>>d[0]>>u[1]>>d[1]; while(h) { w+=h; for(int i=0;i<=1;i++) if(h==d[i]) w-=u[i], w=max(w,0); h--; } cout<<w<<endl; }
題意:在一個無限大的網格上畫正方形,只能畫單位 $1$ 長度的線段,且端點只能在整數格點上。你若是想畫 $(x,y)$ 到 $(x,y+1)$ 這樣一條線段,若是存在 $(x',y)$ 到 $(x',y+1)$ 的另一條線段,則能夠直接畫,不然就須要用尺子。對於 $(x,y)$ 到 $(x+1,y)$ 這樣的線段也是相似的。求最少用幾回尺子能畫出 $n$ 個正方形。htm
題解:顯然,若 $n=k^2$,則 $ans=2 \cdot k$。不然的話,找到知足 $(k-1)^2 < n < k^2$ 的 $k$,而 $ans$ 爲 $2 \cdot k$ 或者 $2 \cdot k - 1$。blog
AC代碼:ci
#include<bits/stdc++.h> using namespace std; const int eps=1e-10; int n; int main() { while(cin>>n) { int k=ceil(sqrt(n)-eps)+eps; if(k*k==n) cout<<2*k<<endl; else { int t=n-(k-1)*(k-1); cout<<((t>=k)?(2*k):(2*k-1))<<endl; } } }
題意:給出一個小寫字母組成的字符串,另外還包含「?」、「*」兩個字符,「?」表明其前面的那個字母能夠去掉或者留下,「*」表明其前面的那個字母能夠重複零到任意屢次。要求你給出一個長度爲 $k$ 的操做後字符串。字符串
題解:首先「Impossible」的緣由有兩種,一種是長度過長,另外一種是長度太短,先把這兩種判掉。get
其次看看有沒有「*」,若是沒有,把一部分「?」前的字母留下來達到長度 $k$ 便可;若是有,那麼別的所有扔掉,只用其中一個「*」重複字母,知道長度爲 $k$。數學
AC代碼:
#include<bits/stdc++.h> using namespace std; int k; string s; int main() { cin>>s>>k; int c1=0, c2=0; for(int i=0;i<s.size();i++) { if(s[i]=='?') c1++; if(s[i]=='*') c2++; } if(s.size()-2*(c1+c2)>k) //長度過長 { printf("Impossible\n"); return 0; } if(c2==0 && s.size()-c1<k) //長度太短 { printf("Impossible\n"); return 0; } int need=k-(s.size()-2*(c1+c2)); //cout<<need<<endl; if(c2>0) { for(int i=0;i<s.size();i++) { if(i+1<s.size() && s[i+1]=='?') {i++; continue;} if(i+1<s.size() && s[i+1]=='*') { for(int t=1;t<=need;t++) printf("%c",s[i]); need=0; i++; continue; } printf("%c",s[i]); } printf("\n"); } else { for(int i=0;i<s.size();i++) { if(i+1<s.size() && s[i+1]=='?') { if(need){printf("%c",s[i]); need--; i++; continue;} else {i++; continue;} } printf("%c",s[i]); } printf("\n"); } }
題意:給出一棵有根樹,根節點編號爲 $1$,每一個節點存在一個權值 $a[x]$,同時還有一個 $s[x]$ 爲從根節點到節點 $x$ 這條路徑上的全部節點的 $a[x]$ 之和。此時,擦除了全部深度爲偶數的節點的 $s[x]$(根節點深度爲 $1$)。而後要求反推出全部節點的 $a[x]$,使得全部節點的 $a[x]$ 之和最小。
題解:很容易就能想到,對於一個 $s[x] = -1$ 節點,它的 $a[x]$ 的取值是受制於它的全部直系子節點的。並且,它的兒子節點們的 $s[y]$ 都是確保已知的,所以只存在兩種狀況:有兒子節點,$s[x]$ 取值就是 $\min_{全部的edge(x,y)}(s[y])$,進而 $a[x] = s[x] - s[par(x)]$;若是沒有兒子節點,那麼顯然取 $a[x] = 0$ 是最好的。而後根據這種思想,用DFS遍歷一下樹,算出每一個節點的 $a[x]$ 就好了。
AC代碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; const int maxn=1e5+10; int n,a[maxn],s[maxn]; vector<int> e[maxn]; bool ok; void dfs(int now,int par,int d) { if(!ok) return; if(d%2==0) { if(e[now].empty()) s[now]=s[par], a[now]=0; else { int mn=INF; for(auto nxt:e[now]) mn=min(mn,s[nxt]); if(mn<s[par]) {ok=0; return;} else s[now]=mn, a[now]=s[now]-s[par]; } } else a[now]=s[now]-s[par]; for(auto nxt:e[now]) dfs(nxt,now,d+1); } int main() { cin>>n; for(int v=2,u;v<=n;v++) scanf("%d",&u), e[u].push_back(v); for(int i=1;i<=n;i++) scanf("%d",&s[i]); ok=1, s[0]=0; dfs(1,0,1); if(!ok) cout<<-1<<endl; else { ll ans=0; for(int i=1;i<=n;i++) ans+=a[i]; cout<<ans<<endl; } }