1. 程式人生 > >[BJOI2018]雙人猜數遊戲

[BJOI2018]雙人猜數遊戲

題解:

徹徹底底的思維題???還是挺難的。。

首先連樣例解釋都沒給。。沒看題解搞了很久

大概就是

一個人要根據另一個人的決策來猜數

可以去看洛谷那篇題解的解釋

然後我們用$f[A/B][i][j][k]$

表示第i次操作時,$A/B$能否判斷出(j,k)

然後這個挺好dp

另外如果$f[i-1][xx]$可以的話$f[i][xx]$也一定可以

後面要注意兩種情況

1.擴展出當前情況的時候

一定要滿足其他的已經擴展出,但是當前的沒有擴展出(因為這個查了很久)

2.最後一次擴充套件的時候,如果只能多擴展出這一個,那也是可行的

這個不知道第一個樣例就過不了

另外答案是兩個之和最小。。。

25組也就1s左右吧

程式碼:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
int n,m;
const int M=300;
bool f[20][M][M];
char cc[10
]; IL bool pd1(bool (*f) [M],int k,int now) { rep(i,m,k) { int j=k-i; if (i>j) break; if (now!=i&&!f[i][k-i]) return(0); } if (!f[now][k-now]) return(1); else return(0); } IL bool pd2(bool (*f) [M],int k,int now) { rep(i,m,k) { int t=k/i; if
(i>t) break; if (t*i==k) if (now!=i&&!f[i][t]) return(0); } if (!f[now][k/now]) return(1); else return(0); } IL bool pd3(bool (*f1) [M],bool (*f2) [M],int k,int now) { rep(i,m,k) { int j=k-i; if (i>j) break; if (now!=i&&f1[i][k-i]!=f2[i][k-i]) return(0); } if (f2[now][k-now]&&!f1[now][k-now]) return(1); else return(0); } IL bool pd4(bool (*f1) [M],bool (*f2) [M],int k,int now) { rep(i,m,k) { int t=k/i; if (i>t) break; if (t*i==k) if (now!=i&&f1[i][t]!=f2[i][t]) return(0); } int t=k/now; if (f2[now][t]&&!f1[now][t]) return(1); else return(0); } int main() { rep(tt,1,25) { me(f); char c1[20]="guess"; int now=4; if (tt>=10) c1[++now]=tt/10+48,c1[++now]=tt%10+48; else c1[++now]=tt%10+48; c1[++now]='.'; c1[++now]='i'; c1[++now]='n'; char c2[20]="guess"; now=4; if (tt>=10) c2[++now]=tt/10+48,c2[++now]=tt%10+48; else c2[++now]=tt%10+48; c2[++now]='.'; c2[++now]='o'; c2[++now]='u'; c2[++now]='t'; freopen(c1,"r",stdin); freopen(c2,"w",stdout); ios::sync_with_stdio(false); cin>>n>>cc>>m; swap(n,m); int tf; if (cc[0]=='B') tf=0; else tf=1; if (!tf) { rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd1(f[2],i+j,i)) f[1][i][j]=1; rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd2(f[2],i*j,i)) f[0][i][j]=1; } else { rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd2(f[2],i*j,i)) f[1][i][j]=1; rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd1(f[2],i+j,i)) f[0][i][j]=1; } rep(k,2,n+1) { rep(i,1,M) rep(j,1,M) f[k][i][j]=f[k-2][i][j]; if ((k+tf)%2==1) { rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd1(f[k-1],i+j,i)) f[k][i][j]=1; } else rep(i,1,M) rep(j,1,M) if (i<=j&&i>=m&&j>=m) if (pd2(f[k-1],i*j,i)) f[k][i][j]=1; } rep(i,1,M) rep(j,1,M) if (i>=m&&j>=m) if ((n+tf)%2==1) { if (pd3(f[n-1],f[n+1],i+j,i)) f[n][i][j]=1; } else { if (pd4(f[n-1],f[n+1],i*j,i)) f[n][i][j]=1; } n++; int mina=1e9,minb=1e9; rep(i,1,M) rep(j,1,M) if (f[n][i][j]&&f[n-1][i][j]&&!f[n-2][i][j]&&!f[n-3][i][j]&&((i+j<mina+minb)||((i+j)==mina+minb&&(i<mina)))) { mina=i,minb=j; } cout<<mina<<" "<<minb<<endl; int a; } return 0; }