C、D略
E
玩交互,中途发现看错2次题意….
这种猜数的交互一般都要二分,所以需要利用他的Y和N二分
先用1e9判N是不是10的若干次方,再用10^k询问找到N的位数,接着可以逐位二分了
注意确定到最后一位的时候要在后面加个0,否则不管最后一位填0~9,答案都会是Y(手测都没发现这个…结果交上去一直不过样例…
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 110;
void query(const ll x){cout<<'?'<<' '<<x<<endl;fflush(stdout);}
char ttt[maxn];
bool get_res(){cin>>ttt;return ttt[0]=='Y'?true:false;}
void answer(const ll x){cout<<'!'<<' '<<x<<endl;fflush(stdout);}
ll pw[maxn],pw9[maxn];
bool e[maxn],e9[maxn];
int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);
ll l=1; for(int i=0;i<=10;i++,l*=10ll) pw[i]=l,query(l),e[i]=get_res();
if(e[10])
{
l=9; for(int i=1;i<=9;i++,l=l*10ll+9ll) query(l),e9[i]=get_res(),pw9[i]=l;
for(int i=9;i>=1;i--) if(!e9[i]) { answer(pw[i]);return 0; }
answer(pw[0]); return 0;
}
int now=8;
while(!e[now]) now--;
if(now==0)
{
for(ll i=1;i<10;i++)
{
query(i*10);
if(get_res()) { answer(i); return 0; }
}
}
else
{
ll k=0;
for(int i=0;i<now;i++)
{
ll l=1,r=9;
while(l<=r)
{
ll mid=l+r>>1;
query(k*10+mid);
if(get_res()) l=mid+1;
else r=mid-1;
}l--;
k=k*10+l;
}
k*=10ll;
for(ll i=0;i<10;i++)
{
query((k+i)*10);
if(get_res()) { answer(k+i); return 0; }
}
}
return 0;
}
F
发现最终图会是一条链,链上的边都是桥,链上每个点挂着若干个联通块
用f[i][j]表示当前的集合为i,链的末端是j,保留的边集权值和的最大值
每次转移在末尾加上新的点l或者枚举一个与i不相交的集合k挂在j上面(其实不一定和j相连,只是把它放在j那一块,只保留l∪j集合内的边)
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;
inline void up(int &x,const int &y){if(x<y)x=y;}
const int maxn = 20;
const int maxm = 81000;
int n,m;
int a[maxn][maxn];
int ct[maxm],f[maxm][maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,c; scanf("%d%d%d",&x,&y,&c);
a[x][y]=a[y][x]=c;
}
int al=1<<n;
for(int i=1;i<al;i++)
{
int j=1;for(;j<=n;j++) if(i>>j-1&1)break;
ct[i]=ct[i^1<<j-1];
for(int k=1;k<=n;k++) if(i>>k-1&1) ct[i]+=a[k][j];
}
for(int i=0;i<al;i++) for(int j=1;j<=n;j++) f[i][j]=-inf;
f[1][1]=0; int re=0;
for(int i=1;i<al;i+=2)
{
for(int j=1;j<=n;j++) if((i>>j-1&1)&&f[i][j]>=0)
{
if(j==n) up(re,f[i][j]);
for(int k=1;k<=n;k++) if(!(i>>k-1&1)&&a[j][k])
up(f[i|1<<k-1][k],f[i][j]+a[j][k]);
int now=al-1-i;
for(int k=now;k;k=k-1&now)
up(f[i|k][j],f[i][j]+ct[k^1<<j-1]);
}
}
printf("%d\n",ct[al-1]-re);
return 0;
}