[考試反思]1026csp-s模擬測試88:發展

不用大家說,我本身來:我頹閃存我沒臉。ios

昨天的想法,ide

今天的回答。函數

生存,優化

發展。spa

總分榜應該稍有回升,可是和上面的差距確定仍是很大。code

繼續。blog

爲昨天的謬誤,承擔代價。隊列

T2和T3都值得張記性。ci

T2由於上次輸出了"-0.00"在文本比較下與"0.0"不一樣致使WA,因此此次輸出的時候把答案加了0.005qt

可是加的太多了,在四捨五入下剛好進位了致使WA。

爲了防止輸出"-0.0"要將答案加一個1e-9級別的數,不要過小也不要太大。

T3算錯上限沒打高精。

考慮極端狀況。考試時不要用__int128(CSP-S不承認)

我不喜歡RP守恆。

我想穩在rank5之內。高不可攀。

 

T1:軍訓隊列。

一個明顯的斜率優化dp。可是考場上推了一會沒有推出來。

然而這題用不到,由於身高最多有6001種,因此$O(6001*6001*k)$可過

可是要注意把全部人身高壓起來後n可能小於k,判掉。

斜率優化的假單調棧能夠當成是一個剪枝。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;  4 double dp[100005][21],h[100005];int n,k,q[100005],qh,qt;  5 double fab2(double x){return x*x;}  6 double cal(int j,int k,int f){return (dp[j][f-1]-dp[k][f-1])/(h[j+1]-h[k+1])+h[j+1]+h[k+1];}  7 int main(){  8     scanf("%d%d",&n,&k);  9     for(int i=1;i<=n;++i)scanf("%lf",&h[i]); 10     sort(h+1,h+1+n);n=unique(h+1,h+1+n)-h-1;h[n+1]=1e9; 11     for(int i=1;i<=n;++i)dp[i][1]=fab2(h[i]-h[1]); 12     for(int j=2;j<=k;++j){ 13         q[qt=qh=1]=0; 14         for(int i=1;i<=n;++i){ 15             dp[i][j]=1e18; 16             while(qt-qh>=1&&cal(q[qh+1],q[qh],j)<h[i]*2)qh++; 17             for(int p=qh;p<=qt;++p)dp[i][j]=min(dp[i][j],dp[q[p]][j-1]+fab2(h[i]-h[q[p]+1])); 18             q[++qt]=i; 19  } 20     }printf("%.2lf\n",dp[n][k]); 21 }
View Code

然而固然也能夠打一個真正的斜率優化。

轉移式是$dp[i][f]=min(dp[j][f-1]+(h[j+1])^2+(h[i])^2-2\times h[j+1] \times h[i])$

而後接下來與i有關的項均可以提出來,剩下的是常數。

而後就能夠獲得一個關於$h[i]$的一次函數(直線)。

由於在這道題裏h是單調的,因此斜率是單調的,取值的橫座標也是單調的。

因此就是一堆直線,能夠維護凸包了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;  4 double dp[100005][21],h[100005],k[100005],b[100005];int n,K,q[100005],qh,qt;  5 double fab2(double x){return x*x;}  6 double cal(int j,double x){return b[j]+k[j]*x;}  7 double jd(int j,int i){return (b[j]-b[i])/(k[i]-k[j]);}  8 int main(){  9     scanf("%d%d",&n,&K); 10     for(int i=1;i<=n;++i)scanf("%lf",&h[i]); 11     sort(h+1,h+1+n);n=unique(h+1,h+1+n)-h-1;h[n+1]=1e9; 12     for(int i=1;i<=n;++i)dp[i][1]=fab2(h[i]-h[1]); 13     for(int j=2;j<=K;++j){ 14         q[qt=qh=1]=j-1;k[j-1]=-2*h[j];b[j-1]=dp[j-1][j-1]+fab2(h[j]); 15         for(int i=j;i<=n;++i){ 16             k[i]=-2*h[i+1];b[i]=dp[i][j-1]+fab2(h[i+1]); 17             while(qt-qh>=1&&cal(q[qh],h[i])>cal(q[qh+1],h[i]))qh++; 18             while(qt-qh>=1&&jd(q[qt-1],i)>jd(q[qt],i))qt--; 19             dp[i][j]=dp[q[qh]][j-1]+fab2(h[i]-h[q[qh]+1]); 20             q[++qt]=i; 21  } 22     }printf("%.2lf\n",dp[n][K]); 23 }
View Code

 

 

 

T2:山屋驚魂

規模不是很大的模擬。雖然說也不小。

預處理一下dize[i][j]表示用i個骰子獲得j的機率。(骰子的英語不是dize。。。打臉。。。可是我懶得改了)

而後。。我也不知道該講什麼。。。模擬好像真的沒辦法講。。。

按照題目說的就是了。不要讀錯題

其實我不是很明白爲何會打的那麼長,並無感受這個模擬比之前的模擬難不少。。。

 1 #include<cstdio>
 2 #include<string>
 3 #include<iostream>
 4 #include<map>
 5 using namespace std;  6 map<string,int>M;  7 long double dize[9][17],pos[101][4098],fail,ans[4][8],lim[102][4][8];  8 int n,st[4],s[102],c1[102],c2[102],num;  9 string bar[4],knd,opt; 10 int chg(int S,int p,int w){return (S^S&7<<p*3)|w<<p*3;} 11 int main(){//freopen("betrayal.in","r",stdin);
12     dize[0][0]=1; 13     for(int i=0;i<=7;++i)for(int j=0;j<=i<<1;++j) 14         dize[i+1][j]+=dize[i][j]/3,dize[i+1][j+1]+=dize[i][j]/3,dize[i+1][j+2]+=dize[i][j]/3; 15     for(int i=0;i<4;++i)cin>>bar[i]>>st[i],st[i]--; 16     cin>>n; 17     pos[0][st[0]|st[1]<<3|st[2]<<6|st[3]<<9]=1; 18     M["Might"]=0;M["Speed"]=1;M["Sanity"]=2;M["Knowledge"]=3; 19     for(int i=0;i<n;++i){ 20         cin>>knd>>opt; 21         if(opt=="<"){ 22             cin>>num; 23             for(int j=0;j<=7;++j)for(int k=0;k<=16;++k)lim[i][M[knd]][j]+=(dize[bar[M[knd]][j]-'0'][k]*(k>=num)); 24             cin>>knd>>opt; 25         }else if(opt=="<="){ 26             cin>>num; 27             for(int j=0;j<=7;++j)for(int k=0;k<=16;++k)lim[i][M[knd]][j]+=(dize[bar[M[knd]][j]-'0'][k]*(k> num)); 28             cin>>knd>>opt; 29         }else if(opt==">"){ 30             cin>>num; 31             for(int j=0;j<=7;++j)for(int k=0;k<=16;++k)lim[i][M[knd]][j]+=(dize[bar[M[knd]][j]-'0'][k]*(k<=num)); 32             cin>>knd>>opt; 33         }else if(opt==">="){ 34             cin>>num; 35             for(int j=0;j<=7;++j)for(int k=0;k<=16;++k)lim[i][M[knd]][j]+=(dize[bar[M[knd]][j]-'0'][k]*(k< num)); 36             cin>>knd>>opt; 37  } 38         s[i]=M[knd]; 39         if(opt[0]=='+')if(opt.length()==3)c2[i]+=opt[1]-'0'; 40             else c1[i]+=opt[1]-'0'; 41         if(opt[0]=='-')if(opt.length()==3)c2[i]-=opt[1]-'0'; 42             else c1[i]-=opt[1]-'0';//printf("%d %d %d\n",s[i],c1[i],c2[i]);
43  } 44     for(int i=0;i<n;++i)for(int S=0;S<1<<12;++S){ 45         int state[4]={S&7,S>>3&7,S>>6&7,S>>9&7}; 46         double rp=pos[i][S]; 47         for(int j=0;j<4;++j)rp*=(1-lim[i][j][state[j]]); 48         pos[i+1][S]+=pos[i][S]-rp; 49         if(c1[i]){ 50             state[s[i]]+=c1[i];state[s[i]]=min(state[s[i]],7); 51             if(state[s[i]]<0)fail+=rp; 52             else pos[i+1][chg(S,s[i],state[s[i]])]+=rp; 53         }else if(c2[i]>=0){ 54             for(int r=0;r<=16;++r){ 55                 double P=rp*dize[c2[i]][r]; 56                 int nw=state[s[i]]+r;nw=min(nw,7); 57                 pos[i+1][chg(S,s[i],nw)]+=P; 58  } 59         }else{ 60             for(int r=0;r<=16;++r){ 61                 double P=rp*dize[-c2[i]][r]; 62                 int nw=state[s[i]]-r; 63                 if(nw<0)fail+=P; 64                 else pos[i+1][chg(S,s[i],nw)]+=P; 65  } 66  }ed:; 67  } 68     printf("%.2Lf\n",fail*100+0.0001); 69     for(int i=0;i<1<<12;++i)for(int k=0;k<4;++k)ans[k][bar[k][i>>k*3&7]-'1']+=pos[n][i]; 70     for(int k=0;k<4;++k,puts(""))for(int i=0;i<8;++i)printf("%.2Lf ",ans[k][i]*100+0.0001); 71 }
2.4k,可寫
 1 #include<cstdio>
 2 #include<string>
 3 #include<iostream>
 4 #include<map>
 5 using namespace std;  6 map<string,int>M;  7 double dize[9][17],pos[101][4098],fail,ans[4][8],lim[102][4][8];  8 int n,st[4],s[102],c1[102],c2[102],num;  9 string bar[4],knd,opt; 10 int chg(int S,int p,int w){return (S^S&7<<p*3)|w<<p*3;} 11 int abs(int a){return a>0?a:-a;} 12 int nt(int a){return a>0?1:-1;} 13 int OPT(string s,int a,int b){return s=="<="?a>b:(s=="<"?a>=b:(s==">="?a<b:a<=b));} 14 int main(){ 15     dize[0][0]=1; 16     for(int i=0;i<8;++i)for(int j=0;j<=i*2;++j) 17         dize[i+1][j]+=dize[i][j]/3,dize[i+1][j+1]+=dize[i][j]/3,dize[i+1][j+2]+=dize[i][j]/3; 18     for(int i=0;i<4;++i)cin>>bar[i]>>st[i],st[i]--; 19     cin>>n; pos[0][st[0]|st[1]<<3|st[2]<<6|st[3]<<9]=1; 20     M["Speed"]=1;M["Sanity"]=2;M["Knowledge"]=3; 21     for(int i=0;i<n;++i){ 22         cin>>knd>>opt; 23         if(opt[0]!='+'&&opt[0]!='-'){ 24             cin>>num; 25             for(int j=0;j<8;++j)for(int k=0;k<=16;++k) 26                 lim[i][M[knd]][j]+=(dize[bar[M[knd]][j]-'0'][k]*OPT(opt,k,num)); 27             cin>>knd>>opt; 28  } 29         s[i]=M[knd]; 30         if(opt.length()==3)c2[i]+=(opt[1]-'0')*(opt[0]=='+'?1:-1); 31         else c1[i]+=(opt[1]-'0')*(opt[0]=='+'?1:-1); 32  } 33     for(int i=0;i<n;++i)for(int S=0;S<1<<12;++S){ 34         int state[4]={S&7,S>>3&7,S>>6&7,S>>9&7}; double rp=pos[i][S]; 35         for(int j=0;j<4;++j)rp*=(1-lim[i][j][state[j]]); 36         pos[i+1][S]+=pos[i][S]-rp; 37         if(c1[i]){ 38             state[s[i]]+=c1[i];state[s[i]]=min(state[s[i]],7); 39             if(state[s[i]]<0)fail+=rp; 40             else pos[i+1][chg(S,s[i],state[s[i]])]+=rp; 41         }else for(int r=0;r<=16;++r){ 42             double P=rp*dize[abs(c2[i])][r]; 43             int nw=state[s[i]]+nt(c2[i])*r;nw=min(nw,7); 44             if(nw<0)fail+=P;else pos[i+1][chg(S,s[i],nw)]+=P; 45  } 46  } 47     printf("%.2lf\n",fail*100+1e-6); 48     for(int i=0;i<1<<12;++i)for(int k=0;k<4;++k)ans[k][bar[k][i>>k*3&7]-'1']+=pos[n][i]; 49     for(int k=0;k<4;++k,puts(""))for(int i=0;i<8;++i)printf("%.2lf ",ans[k][i]*100+1e-6); 50 }
1.8k,壓行

壓行後的代碼不存在任何的複製粘貼了,能夠簡單擴展了。

 

T3:綵球問題

記憶化搜索/dp

狀態4維,12/12/12/4,分別表示還有1/2/3個的球有幾種顏色,且上一次用的球還剩下0/1/2個

而後又是模擬?

最後的答案貌似有$10^{33}$級別?

 1 #include<cstdio>
 2 #define dp re[c1][c2][c3][lst]
 3 __int128 ans,re[13][13][13][3];int cnt[4],n,x;  4 __int128 sch(int c1,int c2,int c3,int lst){  5     if(dp!=-1)return dp;  6     dp=0;  7     if(c1==0&&c2==0&&c3==0)return 1;  8     if(lst==0){  9         if(c1)dp+=c1*sch(c1-1,c2,c3,0); 10         if(c2)dp+=c2*sch(c1+1,c2-1,c3,1); 11         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 12     }else if(lst==1){ 13         if(c1>1)dp+=(c1-1)*sch(c1-1,c2,c3,0); 14         if(c2)dp+=c2*sch(c1+1,c2-1,c3,1); 15         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 16     }else if(lst==2){ 17         if(c1)dp+=c1*sch(c1-1,c2,c3,0); 18         if(c2>1)dp+=(c2-1)*sch(c1+1,c2-1,c3,1); 19         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 20     }return dp; 21 } 22 int main(){ 23     scanf("%d",&n); 24     while(n--)scanf("%d",&x),cnt[x]++; 25     for(int i=0;i<13;++i)for(int j=0;j<13;++j)for(int k=0;k<13;++k)for(int l=0;l<3;++l)re[i][j][k][l]=-1; 26     __int128 x=sch(cnt[1],cnt[2],cnt[3],0); 27     if(x/1000000000000000000ll)printf("%lld",(long long)(x/1000000000000000000ll)); 28     printf("%lld\n",(long long)(x%1000000000000000000ll)); 29 }
你能夠用int128水過
 1 #include<cstdio>
 2 #define dp re[c1][c2][c3][lst]
 3 struct LL{  4     long long x[5];  5     #define mod 100000000
 6     friend void operator+=(LL &a,LL b){  7         for(int i=0;i<5;++i)a.x[i]+=b.x[i];  8         for(int i=0;i<4;++i)a.x[i+1]+=a.x[i]/mod,a.x[i]%=mod;  9  } 10     void print(int i=4){ 11         for(;~i;--i)if(x[i]){printf("%lld",x[i]);break;} 12         for(--i;~i;--i)printf("%08lld",x[i]); 13  } 14     friend LL operator*(int x,LL a){ 15         for(int i=0;i<5;++i)a.x[i]*=x; 16         for(int i=0;i<4;++i)a.x[i+1]+=a.x[i]/mod,a.x[i]%=mod; 17         return a; 18  } 19     friend bool operator!=(LL a,int x){return a.x[0]!=-1;} 20     void operator=(int p){x[0]=p;} 21 }; 22 LL ans,re[13][13][13][3];int cnt[4],n,x; 23 LL sch(int c1,int c2,int c3,int lst){ 24     if(dp!=-1)return dp; 25     dp=0; 26     if(c1==0&&c2==0&&c3==0)return dp=1,dp; 27     if(lst==0){ 28         if(c1)dp+=c1*sch(c1-1,c2,c3,0); 29         if(c2)dp+=c2*sch(c1+1,c2-1,c3,1); 30         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 31     }else if(lst==1){ 32         if(c1>1)dp+=(c1-1)*sch(c1-1,c2,c3,0); 33         if(c2)dp+=c2*sch(c1+1,c2-1,c3,1); 34         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 35     }else if(lst==2){ 36         if(c1)dp+=c1*sch(c1-1,c2,c3,0); 37         if(c2>1)dp+=(c2-1)*sch(c1+1,c2-1,c3,1); 38         if(c3)dp+=c3*sch(c1,c2+1,c3-1,2); 39     }return dp; 40 } 41 int main(){ 42     scanf("%d",&n); 43     while(n--)scanf("%d",&x),cnt[x]++; 44     for(int i=0;i<13;++i)for(int j=0;j<13;++j)for(int k=0;k<13;++k)for(int l=0;l<3;++l)re[i][j][k][l]=-1; 45     sch(cnt[1],cnt[2],cnt[3],0).print(); 46 }
可是顯然做爲一個有臉的人仍是要寫一次高精的

由於真正CSP-S上也不能用__int128,因此就算是模擬賽寫高精也是頗有必要的。

態度必需要有,天人不相欺。

相關文章
相關標籤/搜索