1. 程式人生 > >Wannafly挑戰賽8 ABCD

Wannafly挑戰賽8 ABCD

時隔多年的更新。

Wannafly挑戰賽8:
https://www.nowcoder.com/acm/contest/57#question

A沒什麼好說的= =

#include<stdio.h>

int main()
{
    int h,m,s,t;
    for (char c='a';c!=' ';c=getchar());
    scanf("%d:%d:%d%d",&h,&m,&s,&t);
    printf("%d",(t+h*3600+m*60+s)/(24*3600));
}

B條件等價於三個頂點異色,乘一下就是總個數

#include<stdio.h>

int main()
{
    for(int a,b,c;~scanf("%d%d%d",&a,&b,&c);printf("%d\n",a*b*c));
}

C算是常規DP了,考慮到每個時刻每種做題狀況都是不同的
所以以此設立狀態(狀壓)
f[i][mask]表示的是i時刻已經做完mask的題後還能做完的期望題數
因為在做完一題後只能選擇另一題開始悶頭肝
所以轉移就是列舉沒做的題目,分別計算期望最大收益
驗證一下發現複雜度符合要求

#include<stdio.h>
#include<algorithm>
using namespace std; bool vis[181][64]; double f[181][64],p[6][181]; int n,m; void dfs(int t,int mask) { if (vis[t][mask]) return; vis[t][mask]=1; for (int i=0;i<n;i++) if (!(mask&(1<<i))) { double tmp=0; for (int j=t+1;j<=m;j++) { dfs(j,mask^(1<<i));
tmp+=p[i][j-t]*(1+f[j][mask^(1<<i)]); } f[t][mask]=max(f[t][mask],tmp); } } int main() { scanf("%d%d",&n,&m); for (int i=0;i<n;i++) for (int j=1;j<=m;j++) scanf("%lf",p[i]+j); dfs(0,0); printf("%.5f",f[0][0]); }

D剛開始看這題發現也是很常規的(至少對於高中數學水平來說)
直接把思考過程放出來吧:
注意以下的推導過程中n的含義有變化
(簡單來說n+m表示的是題面的n,其他的n僅相當於一個變數)

f[n]=p*(f[n+1])+(1-p)*f[n-1]
f[n+m]=1
f[0]=0

f[1]=p*f[2]+
f[2]=p*f[3]+(1-p’)*f[1]
=。。。

f[n]=k*f[n+1]
f[n+1]=p*f[n+2]+p’*f[n]
=p*f[n+2]+p’*k*f[n+1]
=f[n+2]*p/(1-p’*k)
k’=p/(1-p’*k) //p=up/dn
//p’=(dn-up-mid)/dn
=up/(dn-(dn-mid-up)*k)
這通過率我懷疑是被卡了精

忘了考慮平局

f[n]=win*f[n+1]+loss*f[n-1]+fair*f[n]
f[n+m]=1
f[0]=0
f[n-1]=k[n-1]*f[n]
f[n]=f[n+1]*win/(1-k[n-1]*loss-fair)
k[n]=win/(1-k[n-1]*loss-fair)
=up/(dn-k[n-1]*(dn-up-mid)-mid)

f[1]=win*f[2]+fair*f[1]
k[1]=win/(1-fair)
=up/(dn-mid)

………………………………
。。
為啥這麼少人過……

EF看著就不想動= =
不會做不會做,撤了

以上就是D題的思考過程
總結一下
f[n]=winf[n+1]+lossf[n1]+fairf[n]
f[n+m]=1
f[0]=0
這是基本關係,f表示勝率
推導的時候肯定是想減少變數,每個變數都和前後項有關,不可能解
注意到那個0,拿0開刀

f[1]=winf[2]+fairf[1]
f[1]=f[2]win1fair
這條東西繼續帶,會發現一條形式相近的f[2]與f[3]的關係式
記為 f[n1]=k[n1]f[n]
嘗試往原本的式子裡帶,會發現下面的關係
f[n]=f[n+1]win1k[n1]lossfair
k[n]=win1k[n1]lossfair
k[1]=win1fair
說明k的每一項都是可以推出來的
回到大前提 f[n+m]=1 結合 f[n1]=k[n1]f[n]
就可以解出f[n]了

#include<stdio.h>
 
int n,m,l,r,L,R,up,dn,mid;
double k[200005],ans=1; 
 
int main()
{
    scanf("%d%d%d%d%d%d",&n,&l,&r,&m,&L,&R);
    for (int i=l;i<=r;i++) for (int j=L;j<=R;j++){dn++;if (j<i) up++;if (j==i) mid++;}
    k[1]=(up+0.0)/(dn-mid);
    for (int i=2;i<m+n;i++) k[i]=up/(dn-k[i-1]*(dn-up-mid)-mid);
    for (int i=n;i<m+n;i++) ans*=k[i];
    printf("%.5f",ans);
}