题意:还没读懂.....
题意:交互题,你要求一个点的位置,这个点在1到n之中,每次可以移动至多k步,你每次可以询问系统一个区间 [ L , R ],系统会告诉你这个点在该时刻是否在区间内,要求至多用4500次求出这个点的坐标。
思路:先用二分缩小目标点的可确定区间,直到区间缩小的一定值后,随机询问某个点,看答案是否是它,若不是就扩大确定范围继续二分即可。由于 k 的值最大不过10,因此可以用随机算法而且可以在较短的询问次数内随机求出目的点位置。
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
char s[5];
ll n,k;
int ss(ll l,ll r)
{
printf("%I64d %I64d\n",l,r);
cin>>s;
if(s[0]=='Y')return 1;
return 0;
}
int main()
{
srand(23333);
cin>>n>>k;
ll l=1,r=n;
while(1)
{
l=max(1ll,l-k);
r=min(n,r+k);
if(r-l<=4*k)
{
ll w=rand()%(r-l+1)+l;
if(ss(w,w))return 0;
}
else
{
ll m=(l+r)/2;
if(ss(l,m))r=m;
else l=m+1;
}
}
}
题意:给你一个n个点,m条边的无向图,每个点有权值,给你一个范围[ 0 , 2^k-1 ],你可以从这个范围内选择一个数 x,然后从图中选择任意一些点的集合 s,使得集合内所有点都异或 x 后,原图每条边连接的两个点的值都不相等(保证原始图每条边连接的两个点权值不同),求有多少种组合( x ,s )。
思路:对于每条边连接的 u v,我设边权为wi=au^av,如果点u或点v只有一个点异或了wi,就非法,因此我先排除掉所有的wi(假设总共有cnt个不同的wi),对于每个点,我可以选择加入集合或者不加,因此有2^n中情况,加入集合后 x 有2^k-cnt个取值,因此一共有(2^k-cnt)*2^n种组合,但是对于边权为 wi 的边,我可以把u v看成同一个点,要么同时异或wi,要么都不异或,因此还漏一些组合,之前的数再加上现在漏掉的数就是答案了。
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
const int maxn=5e5+10,mod=1e9+7;
typedef long long ll;
map<ll,int>mp;
struct node
{
int x,y;
node(int a,int b){x=a,y=b;}
};
vector<node>G[maxn];
ll a[maxn],p[maxn],par[maxn];
void init(int n)
{
p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*2%mod,par[i]=i;
}
int find(int x)
{
if(par[x]!=x)
par[x]=find(par[x]);
return par[x];
}
int Union(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
par[fx]=fy;
return 1;
}
return 0;
}
int main()
{
int n,m,k,u,v,cnt=0;
scanf("%d%d%d",&n,&m,&k);
init(n);
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
ll x=a[u]^a[v];
if(!mp[x])mp[x]=++cnt;
G[mp[x]].push_back(node(u,v));
}
ll ans=((1ll<<k)-cnt)%mod*p[n]%mod;
for(int i=1;i<=cnt;i++)
{
int s=n;
for(int j=0;j<G[i].size();j++)
if(Union(G[i][j].x,G[i][j].y))
s--;
ans=(ans+p[s])%mod;
for(int j=0;j<G[i].size();j++)
{
int x=G[i][j].x,y=G[i][j].y;
par[x]=x,par[y]=y;
}
}
printf("%I64d\n",ans);
}