【高中組集體賽前熱身賽】題解
阿新 • • 發佈:2018-02-21
i++ algo 1.0 iostream 滿足 gin mar print 每一個
(第一次給學弟們學妹寫題解,可能有些地方我認為簡單的可能沒有仔細解釋,所以導致沒有講清楚的一定要勤奮問百度,或者底下留言)
【A-投擲硬幣】
題解:基礎DP(動態規劃),dp[i][j]表示從第一個硬幣開始翻,翻到第i個硬幣的時候,翻到正面的有j個。那麽dp[i][j]由dp[i-1][j-1](第i個是正面)和dp[i-1][j](第i個是反面)轉移而來。所以由方程:dp[i][j]=dp[i-1][j]*(1.0-p[i])+dp[i-1][j-1]*p[i];當然j=0的話只能優dp[i-1][0]轉移而來。
#include<cstdio>
#include<cstdlib>
#include <cstring>
#include<iostream>
using namespace std;
const int maxn=1010;
double dp[maxn][maxn],p[maxn];
int main()
{
int N,M,i,j;
scanf("%d%d",&N,&M);
dp[0][0]=1.0;
for(i=1;i<=N;i++) scanf("%lf",&p[i]);
for(i=1;i<=N;i++){
dp[i][0]=dp[i-1][0 ]*(1.0-p[i]);
for(j=1;j<=M;j++){
dp[i][j]=dp[i-1][j]*(1.0-p[i])+dp[i-1][j-1]*p[i];
}
}
printf("%.4lf\n",dp[N][M]);
return 0;
}
【B-最大集合】
題解:每一個集合是封閉的。即每個元素只會出現在一個集合裏面,而且從每個集合的任意元素出發,都可以走到下一個元素,直到走到起始元素。
所以DFS搜索就可以了,把每次搜索到的標記一下。對於沒有搜索到的,作為起點,繼續搜索。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=100010; int vis[maxn],a[maxn],cnt; int main() { int N,i,ans=0,tmp; scanf("%d",&N); for(i=1;i<=N;i++) scanf("%d",&a[i]); for(i=1;i<=N;i++){ if(vis[i]==0){ cnt=1; tmp=i; vis[tmp]=1; while(!vis[a[tmp]]){ cnt++; tmp=a[tmp]; } ans=max(ans,cnt); } } printf("%d\n",ans); return 0; }
【C-第K小分數】
枚舉每一個數為分母,然後二分分子。 二分的復雜度是O(logn),然後枚舉N個數作為分母,這樣的話復雜度就是O(N*logN)。不會二分的仔細看代碼就會了。
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=1010; ll a[maxn],N; ll check(int x,int y) { ll res=0; for(int i=1;i<=N;i++){ res+=(a[i]*x/y); } return res; } int main() { ll K,L,R,Mid,tmp; scanf("%lld%lld",&N,&K); for(int i=1;i<=N;i++) scanf("%d",&a[i]); for(int i=1;i<=N;i++){ L=1; R=a[i]-1; while(L<=R){ Mid=(L+R)/2; tmp=check(Mid,a[i]); if(tmp==K){ printf("%lld/%lld\n",Mid,a[i]); return 0; } else if(tmp<K) L=Mid+1; else R=Mid-1; } }return 0; }
【D-最大子矩陣】
由於A>=1滿足區間和的單調性。所以可以用雙指針,即枚舉矩形的上下邊界,然後移動左右邊界
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=300; int N,M,K,a[maxn][maxn],sum[maxn][maxn]; int vis[10010],num,Now,ans=-1; int main() { int i,j,k,L,R; scanf("%d%d%d",&N,&M,&K); for(i=1;i<=N;i++) for(j=1;j<=M;j++){ scanf("%d",&a[i][j]); sum[i][j]=sum[i-1][j]+a[i][j]; } for(i=1;i<=N;i++) for(j=i;j<=N;j++){ memset(vis,0,sizeof(vis)); num=0; Now=0; for(R=1,L=1;R<=M;R++){ num+=j-i+1; Now+=sum[j][R]-sum[i-1][R]; while(Now>K&&L<=R) { num-=j-i+1; Now-=sum[j][L]-sum[i-1][L]; L++; } if(Now<=K&&L<=R) ans=max(ans,num); } } printf("%d\n",ans); return 0; }
【高中組集體賽前熱身賽】題解