清北學堂國慶day5解題報告
阿新 • • 發佈:2017-10-12
space 枚舉 color stream pri font align code efi
Day5解題報告
張炳琪
時間安排::
T1:想了很久,一個多小時寫的暴力
T2:一小時左右
T3:一小時以內
答題情況和錯誤分析::
T1: 30
考場上沒推出來,想復雜了,拆分的二進制只得了暴力分
T2:70
寫的比較穩妥的根號枚舉暴力
T3:60
寫了個剪枝搜索,打了個暴力
Tot::160
題目解析:
T1:
先將數據從小到大排序,然後線性掃一遍,一邊掃一邊求和,當下一個數字比以前所求的所有數字之和還要大1以上的時候,就不滿足情況,這時應當終止並且輸出。
T2:
正解是二分最小單個連續值區間,O1計算兩邊的值
歪解是開根號乘以二再減一也能A
我的方法是一種找連續區間的方法,但只是枚舉,所以過不了所有點
T3:從60%的數據中我們得到其實,這個題目搜索的復雜度已經不錯了,但是2^30依舊過不了,這時用了一個我以前沒用過的知識點,就是分成兩塊搜索,然後合並狀態,聽老師講完就比較好寫了;
合並的時候采用二分合並的方法,第一次搜索出所有狀態後對於狀態進行排序,首先按照鉆石個數,其次按照拿到的價值,之後第二次搜索對於每個得到的狀態二分找尋所有符合要求的條件
代碼:
T1
#include<cstdio> #include<iostream> #include<algorithm> #define MAXN 100100 using namespace std; longlong note[MAXN]; int n; int main() { freopen("lost.in","r",stdin);freopen("lost.out","w",stdout); scanf("%d",&n); for(int i = 1;i <= n;i++) scanf("%lld",¬e[i]); sort(note + 1,note + n + 1); long long tot = 0; for(int i = 1;i <= n;i++) { if(note[i] > tot + 1) { break; } tot += note[i]; } cout << tot + 1; return 0; }
T2:
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> using namespace std; long long n; int main() { freopen("div.in","r",stdin);freopen("div.out","w",stdout); cin >> n; long long q = sqrt(n); long long ans = q * 2; if(q * (q + 1) > n)ans--; cout << ans ; return 0; }
T3;
#include<cstdio> #include<algorithm> using namespace std; struct Note{ int k; int ver; double gai; }note[923456]; double qian[31][9876]; int ver[31][9876]; int tp[31]; int top = 0; int n,m; int v[99]; double p[99]; double ans[99]; int zz; void dfs(int step,int zuan,int mon,double gai) { if(step == zz + 1) { top++; note[top].gai = gai; note[top].k = zuan; note[top].ver = mon; return; } dfs(step + 1,zuan + 1,mon,gai * (1 - p[step])); dfs(step + 1,zuan,mon + v[step],gai * p[step]); } int find(int k,int mon) { int l = 1,r = tp[k]; while(l + 1 < r) { int mid = (l + r) >> 1; if(ver[k][mid] >= mon)l = mid; else r = mid; } if(ver[k][r] >= mon)return r; if(ver[k][l] >= mon)return l; return -1; } void check(int zuan,int mon,double gai) { for(int i = 0;i <= n - zuan;i++) { int zz = m - mon; int q = find(i,zz); if(q == -1)continue; ans[i + zuan] += qian[i][q] * gai; } } void rdfs(int step,int zuan,int mon,double gai) { if(step == n + 1) { check(zuan,mon,gai); return; } rdfs(step + 1,zuan + 1,mon,gai * (1 - p[step])); rdfs(step + 1,zuan,mon + v[step],gai * p[step]); } bool cmp(Note a,Note b) { return a.k == b.k ? a.ver > b.ver : a.k < b.k; } int main() { freopen("diamond.in","r",stdin);freopen("diamond.out","w",stdout); scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) { scanf("%d%lf",&v[i],&p[i]); p[i] /= 100.0; } zz = n / 2; dfs(1,0,0,1.0); sort(note + 1,note + top + 1,cmp); for(int i = 1;i <= top;i++) { tp[note[i].k]++; ver[note[i].k][tp[note[i].k]] = note[i].ver; qian[note[i].k][tp[note[i].k]] = qian[note[i].k][tp[note[i].k] - 1] + note[i].gai; } rdfs(zz+1,0,0,1.0); for(int i = 0;i <= n;i++) printf("%.3lf\n",ans[i]); return 0; }
清北學堂國慶day5解題報告