# BZOJ2798/POI 2012 Bidding

Task
A和B两个人在玩一个游戏，这个游戏是他们轮流操作一对整数(x,y)。

1. 将(x,y)变成(1,x+y)。
2. 将(x,y)变成(2x,y)。
3. 将(x,y)变成(3x,y)。

1. int inicjuj(); 开始时调用，返回n的值。
2. void alojzy(int x); A进行一次操作，x表示操作编号。
3. int bajtazar(); 获得B的操作编号。


#include "cliclib.h"
int main() {
int n = inicjuj();
while (true) {
alojzy(1);
int x = bajtazar();
}
return 0;
}


Solution

x=2a3b$x=2^a*3^b$.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cliclib.h>
#define my_op alojzy
#define he_op bajtazar
using namespace std;
const int M=30005;
const int S2=16,S3=11;
int f2[S2],f3[S3];
bool dp[S2][S3][M];
int inicjuj(){return 0;}
void my_op(int a){};
int he_op(){return 0;}
int main(){
int i,j,k,n=inicjuj();
int sum=0,a=0,b=0;
f2=f3=1;
for(i=1;i<S2;i++)f2[i]=f2[i-1]*2;
for(i=1;i<S3;i++)f3[i]=f3[i-1]*3;
for(k=n;k>=0;k--){
for(i=S2-1;i>=0;i--){
for(j=S3-1;j>=0;j--){
int v=k+f2[i]*f3[j];
if(v>=n)dp[i][j][k]=false;
else{
int f=0;
if(i+1>=S2||j+1>=S3)f|=1;
else if(!dp[v]||!dp[i+1][j][k]||!dp[i][j+1][k])f=1;
dp[i][j][k]=f;
}
}
}
}
while(true){
if(a+1>=S2||!dp[a+1][b][sum])my_op(2),a++;
else if(b+1>=S3||!dp[a][b+1][sum])my_op(3),b++;
else my_op(1),sum+=f2[a]*f3[b],a=b=0;
int y=he_op();
if(y==1){sum+=f2[a]*f3[b];a=b=0;}
else if(y==2)a++;
else b++;
}
return 0;
}