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表示勝率
推導的時候肯定是想減少變數,每個變數都和前後項有關,不可能解
注意到那個0,拿0開刀
這條東西繼續帶,會發現一條形式相近的f[2]與f[3]的關係式
記為
嘗試往原本的式子裡帶,會發現下面的關係
又
說明k的每一項都是可以推出來的
回到大前提
就可以解出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);
}