連接:http://codeforces.com/contest/1068c++
題意:一共 $N$ 種硬幣,我已經有其中 $K$ 種,個人 $M$ 個朋友每人送我等數量的硬幣,且送來的每一枚硬幣都不屬於同一種,要求最後我收到手上的硬幣至少有 $L$ 種是我沒有的,求每一個人最少送幾枚硬幣。數組
題解:即求知足 $K + L \le aM \le N$ 的最小正整數 $a$。spa
AC代碼:code
#include<bits/stdc++.h> typedef long long ll; using namespace std; ll n,m,k,l; int main() { cin>>n>>m>>k>>l; if(m>n) { cout<<-1<<endl; return 0; } if(k+l<=m) { cout<<1<<endl; return 0; } ll a; if((k+l)%m==0) a=(k+l)/m; else a=(k+l)/m+1; if(a*m>n) cout<<-1<<endl; else cout<<a<<endl; }
題意:給定正整數 $b(b \le 10^{10})$,對於 $1 \le a \le 10^{18}$,求 $\frac{{{\mathop{\rm lcm}\nolimits} (a,b)}}{a}$ 的不一樣取值個數。blog
題解:$\frac{{{\mathop{\rm lcm}\nolimits} (a,b)}}{a} = \frac{{ab}}{{a\gcd (a,b)}} = \frac{b}{{\gcd (a,b)}}$,即求 $b$ 的因數個數。ci
AC代碼:get
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n; int main() { cin>>n; ll cnt=0; for(ll i=1;i*i<=n;i++) { if(n%i==0) { if(i*i==n) cnt++; else cnt+=2; } } cout<<cnt<<endl; }
題意:it
給定一個 $10^9 \times 10^9$ 的正方形網格,現有 $n$ 種顏色,給若干個棋子上色(每種顏色都要塗至少一個棋子),又給出 $m$ 個顏色對 $(x,y)$ 表示這兩個顏色是協調的。class
如今對於同一種顏色內的棋子集合,以及兩個和諧的顏色對構成的棋子並集,都要知足連通性質,該性質的意思即:「首先規定棋子只能夠走直線的任意距離,且能夠徹底不理睬非同集合內的棋子,但只有當它遇到同集合內的另外一個棋子時才能夠轉彎。而該集合中任意一個棋子,都它能夠走到集合內的任意其餘棋子的位置。」test
如今你要給出任意一種可行的放置棋子的方案。
題解:
首先,第 $i$ 行所有給第 $i$ 種顏色,不得放其餘顏色。爲了防止某種顏色沒有塗棋子,能夠先在 $(i,i)$ 位置放上顏色爲 $i$ 的棋子。
而後對於給出的任意兩個協調顏色,依次在後面的 $n+1, n+2, \cdots$ 列裏放上對應行數的兩枚棋子。
AC代碼:
#include<bits/stdc++.h> using namespace std; int n,m; vector<int> ans[105]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) ans[i].push_back(i); int col=n+1; for(int i=1,u,v;i<=m;i++) { scanf("%d%d",&u,&v); if(u==v) continue; ans[u].push_back(col); ans[v].push_back(col); col++; } for(int i=1;i<=n;i++) { printf("%d\n",ans[i].size()); for(int k=0;k<ans[i].size();k++) printf("%d %d\n",i,ans[i][k]); } }
題意:給定一個長度爲 $n(n \le 1e5)$ 的數組 $a[1:n]$,$a[i]$ 的值域爲 $1$ 到 $200$,且每一個數的旁邊必須有一個不小於它的數。而有些數字被擦掉了,如今問共有多少種可行的填充方案。
題解:
看到這題第一感受就dfs暴力搜索,然而時間複雜度顯然不行,所以考慮dp。
考慮 $dp[i][x][0,1,2]$ 的表示的狀態爲已經肯定了第 $i$ 個數字爲 $x$,而 $0,1,2$ 分別表示第 $i-1$ 個數 $w$ 是小於、等於或大於 $x$。其存儲的值是其狀態下的方案數。
那麼就有狀態轉移方程(固然這是創建在第 $i+1$ 位能夠填 $y$ 的前提下的):
$\begin{array}{l} dp[i + 1][y][0] = \sum\limits_{x = 1}^{y - 1} {dp[i][x][0,1,2]} \\ dp[i + 1][y][1] = dp[i][y][0,1,2] \\ dp[i + 1][y][2] = \sum\limits_{x = y + 1}^{200} {dp[i][x][1,2]} \\ \end{array}$
邊界條件,考慮到第 $1$ 個數左邊是空的,至關於左邊是一個更小的數,所以有(依然是創建在第一位能填入 $x$ 的前提下):
$\begin{array}{l} dp[1][x][0] = 1 \\ dp[1][x][1] = 0 \\ dp[1][x][2] = 0 \\ \end{array}$
AC代碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int maxn=1e5+5; int n,a[maxn]; ll sum,dp[maxn][203][3]; int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int x=1;x<=200;x++) { if(a[1]!=-1 && a[1]!=x) dp[1][x][0]=dp[1][x][1]=dp[1][x][2]=0; else dp[1][x][0]=1, dp[1][x][1]=dp[1][x][2]=0; } for(int i=2;i<=n;i++) { sum=0; for(int y=1;y<=200;y++) { if(a[i]!=-1 && a[i]!=y) dp[i][y][0]=0; else dp[i][y][0]=sum; sum+=(dp[i-1][y][0]+dp[i-1][y][1]+dp[i-1][y][2])%mod; sum%=mod; } for(int y=1;y<=200;y++) { if(a[i]!=-1 && a[i]!=y) dp[i][y][1]=0; else dp[i][y][1]=(dp[i-1][y][0]+dp[i-1][y][1]+dp[i-1][y][2])%mod; } sum=0; for(int y=200;y>=1;y--) { if(a[i]!=-1 && a[i]!=y) dp[i][y][2]=0; else dp[i][y][2]=sum; sum+=(dp[i-1][y][1]+dp[i-1][y][2])%mod; sum%=mod; } } ll ans=0; for(int x=1;x<=200;x++) ans+=(dp[n][x][1]+dp[n][x][2])%mod, ans%=mod; cout<<ans<<endl; }
題意:
一個連通無向圖,若僅有一個節點度數不小於 $3$,其餘全部節點度數均爲 $1$,則稱爲「刺蝟」。如今定義「$k$-刺蝟」,爲:
「$1$-刺蝟」即普通「刺蝟」;
對於「$k$-刺蝟」,其由「$k-1$-刺蝟」變化而來,將「$k-1$-刺蝟」的全部度數爲 $1$ 的頂點換成一個「$1$-刺蝟」的中心,即構成「$k$-刺蝟」。
如今給你一張圖和一個 $k$,讓你判斷這張圖是否爲「$k$-刺蝟」。
題解:
首先,當 $k=11$ 時,節點數最少也須要 ${\sum_{i=0}^{11}{3^i}} = 265720$ 個頂點,顯然已經不夠了,因此對於 $k \ge 11$ 的狀況能夠直接判斷不行。
接下來,能夠考慮以全部度數爲零的節點爲起始,將它們的深度定義爲 $0$。而後自底向上地進行BFS(或者說BFS的一種變形?),同時不斷地刪除葉子結點。
對於每一個節點,都須要判斷它的深度和度數是否可行,還要判斷其父親節點是否只有一個。
對於最後一個沒有父親節點的根節點,判斷他的深度是否等於 $k$。
AC代碼:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int maxm=2e5+10; int n,k; int degree[maxn]; struct Edge{ int u,v; int next; }; Edge E[maxm]; int head[maxn],ne; void init() { ne=0; memset(head,0,sizeof(head)); } void addedge(int u,int v) { ++ne; E[ne].u=u, E[ne].v=v; E[ne].next=head[u]; head[u]=ne; } int dist[maxn]; bool del[maxn],vis[maxn]; bool bfs() { queue<int> Q; for(int i=1;i<=n;i++) { if(degree[i]==1) Q.push(i), vis[i]=1, dist[i]=0; else vis[i]=0; } memset(del,0,sizeof(del)); while(!Q.empty()) { int u=Q.front(); Q.pop(); del[u]=1; //將節點刪除 int cnt=0; //記錄父親節點個數 for(int i=head[u];i;i=E[i].next) { int v=E[i].v; if(del[v]) continue; else cnt++; if(cnt>1) return false; //父親節點應當只有一個 if(!vis[v]) { vis[v]=1; dist[v]=dist[u]+1; Q.push(v); } else { if(dist[v]!=dist[u]+1) return false; } } if(cnt==0) { //當前節點是根節點 if(degree[u]<3) return false; if(dist[u]!=k) return false; } else if(degree[u]>1) { //當前節點不是根節點也不是葉子結點 if(degree[u]<=3) return false; } } return true; } int main() { cin>>n>>k; init(); memset(degree,0,sizeof(degree)); for(int i=1,u,v;i<n;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); degree[u]++; degree[v]++; } if(n<4 || k>=11) printf("No\n"); else printf("%s\n",bfs()?"Yes":"No"); }