[考试总结]noip模拟77
话说开始下午考试了,然后改题飞快还不是因为数据太水了所以这一次就不咕了。
最大或
这个题目还是比较玄学的。
首先可以发现在两个二进制数的位数不相同的时候,那么答案就一定是所有都是 \(1\) 的长度为 \(r\) 的位数的二进制。
那么位数相同的时候该怎么办呢?
然后开始猜结论
因为暴力过于好写,所以猜一个结论就对拍一次。
然后发现如果在两个数的第一个不相同的位那里后面全部设置成 \(1\) 就不会错误了。
然后这个题目就能有了。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define debug std::cerr<<"debug"<<endl
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define scanf ak = scanf
#define gec() getchar()
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch = gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9 + 10;ll llinf = 1e18;
#define int long long
namespace xin
{
auto ws = [](int x) -> int
{
throw(i,63,1)
if(x & (1ll << i - 1))
return i;
return 0ll;
};
auto ci = [](int x) -> int
{
bool ok = 0;
throw(i,63,1)
if(!ok and x & (1ll << i - 1))
ok = 1;
else if(ok and x & (1ll << i - 1))
return i;
return 0ll;
};
auto dif = [](int x,int y) -> int
{
throw(i,63,1)
if((x & (1ll << i - 1)) != (y & (1ll << i - 1)))
return i;
return 1ll;
};
inline short main()
{
file(maxor);
int T; io >> T;
while(T--)
{
register int l,r; io >> l >> r;
if(ws(r) != ws(l))
printf("%lld\n",r|((1ll << ws(r) - 1) - 1));
else
printf("%lld\n",r|((1ll << dif(r,l) - 1) - 1));
}
return 0;
}
}
signed main() {return xin::main();}
答题
meet in middle
好题,没看出来部分分数有一个背包,但是直觉告诉我这个题目是 meet in middle
,所以打了之后发现后面的取值不是很会处理。
其实二分就行
所以只能一个一个加上去,然后也有不少分数。
对于两个序列,如果你要寻找他们所有加和排名为 \(k\) 的数,使用单调指针加二分就可以解决。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define debug std::cerr<<"debug"<<endl
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define scanf ak = scanf
#define gec() getchar()
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch = gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 2e6+10,inf = 1e9 + 10;ll llinf = 1e18;
#define int long long
namespace xin
{
const double eps = 1e-8;
#define equal(x,y) (fabs(x - y) <= eps)
int a[maxn],zhi = 0;
int he[maxn],cnt;
int n,c[maxn];
double p;
void dfs(int ms)
{
if(zhi == ms)
{
++cnt;
try(i,1,zhi) he[cnt] += c[a[i]];
// try(i,1,zhi) cout<<a[i]<<' ';
// cout<<endl;
return ;
}
try(i,a[zhi]+1,n)
{
a[++zhi] = i;
dfs(ms);
zhi --;
}
}
int he1[maxn],he2[maxn],vis1[maxn],vis2[maxn];
int cnt1 = 1,cnt2 = 1;
int maxx;
void dfs1(int ms)
{
if(zhi == ms)
{
++cnt1;
try(i,1,zhi) he1[cnt1] += c[a[i]];
return ;
}
try(i,a[zhi]+1,(n>>1))
{
a[++zhi] = i;
dfs1(ms);
zhi --;
}
}
void dfs2(int ms)
{
if(zhi == ms)
{
++cnt2;
try(i,1,zhi) he2[cnt2] += c[a[i]];
// try(i,1,zhi) cout<<a[i]<<' '; cout<<endl;
return ;
}
try(i,a[zhi]+1,n)
{
a[++zhi] = i;
dfs2(ms);
zhi --;
}
}
int sum;
inline bool check(int x,int pos)
{
int pi = cnt2,tot = 0;
try(i,1,cnt1)
{
while(pi and he2[pi] + he1[i] > x) pi --;
tot += pi;
}
return ((1.0*tot)/((long double)(1ll<<n)))>=p;
// return tot >= pos;
}
inline short main()
{
#ifdef ONLINE_JUDGE
file(answer);
#endif
scanf("%lld%lf",&n,&p);
try(i,1,n) io >> c[i],sum += c[i];
if(n <= 20)
{
try(i,1,n) dfs(i);
he[++cnt] = 0;
std::sort(he+1,he+cnt+1);
// try(i,1,cnt) jb(he[i]);
cout<<he[(int)std::ceil(cnt * p)]<<endl;
// jb((int)std::ceil(cnt * p));
}
else
{
try(i,1,n / 2) dfs1(i); a[0] = n / 2;
try(i,1,n / 2) dfs2(i);
vis1[0] = vis2[0] = 1;
int pos = (int)std::ceil((1ll << n) * p);
// jb(pos);
int num = 0;
// try(i,1,cnt2) cout<<he2[i]<<' '; cout<<endl;
std::sort(he1+1,he1+cnt1+1); std::sort(he2+1,he2+cnt2+1);
int l = 1,r = sum,res = sum;
while(l<=r)
{
register int mid = l + r >> 1;
if(check(mid,pos)) r = mid - 1, res = mid;
else l = mid + 1 ;
}
cout<<res<<endl;
}
return 0;
}
}
signed main() {return xin::main();}
联合权值
这个暴力有 \(95pts\) ,然后大力卡常。。。。
正解不会。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define debug std::cerr<<"debug"<<endl
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define scanf ak = scanf
#define gec() getchar()
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch = gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 3e4+10,inf = 1e9 + 10,two = 2e2+10;ll llinf = 1e18;
#define int long long
namespace xin
{
std::bitset<maxn>link[maxn],temp;
int n,m,t;
int sum[maxn];
int ans1,ans2;
std::queue<int>q;
bool vis[maxn];
int w[maxn];
std::vector<int>vec[maxn];
int l1[maxn],l2[maxn];
inline short main()
{
file(link);
io >> n >> m >> t;
try(i,1,m)
{
register int x,y; io >> x >> y;
vec[x].push_back(y); vec[y].push_back(x);
link[x][y] = link[y][x] = 1;
l1[i] = x; l2[i] = y;
}
try(i,1,n) io >> w[i];
try(i,1,m)
{
sum[l1[i]] += w[l2[i]];
sum[l2[i]] += w[l1[i]];
}
try(i,1,n)
{
ans1 += sum[i] * sum[i];
ans1 -= w[i] * w[i] * link[i].count();
}
try(i,1,m)
{
register int x = l1[i],y = l2[i];
temp = link[x] & link[y];
register int zhuan = temp.count();
ans1 -= 2 * zhuan * w[x] * w[y];
}
try(x,1,n)
{
std::sort(vec[x].begin(),vec[x].end(),[](int x,int y){return w[x] > w[y];});
try(i,0,(int)vec[x].size()-1) try(j,i+1,(int)vec[x].size()-1)
{
register int u = vec[x][i],v = vec[x][j];
if(w[u] * w[v] < ans2) break;
if(!link[u][v]) ans2 = w[u] * w[v];
}
}
if(t xor 2) cout<<ans2<<endl;
else cout<<0<<endl;
if(t xor 1) cout<<(ans1 ? ans1 : -1)<<endl;
else cout<<0<<endl;
return 0;
}
}
signed main() {return xin::main();}
主仆见证了 Hobo 的离别
零操作连正边,否则连反边。
然后每次 \(dfs\)
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define debug std::cerr<<"debug"<<endl
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define scanf ak = scanf
#define gec() getchar()
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch = gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9 + 10,two = 5e3+10;ll llinf = 1e18;
namespace xin
{
class xin_edge{public:int next,ver;}edge[maxn];
int head[maxn],rp;
inline void add(int x,int y) {edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;}
int n,m;
bool vis[maxn];
bool dfs(int x,int k)
{
vis[x] = 1;
go(i,x)
{
if(vis[y]) continue;
if(y == k) return 1;
if(dfs(y,k)) return 1;
}
return false;
}
inline short main()
{
#ifdef ONLINE_JUDGE
file(friendship);
#endif
io >> n >> m;
try(i,1,m)
{
register int fg; io >> fg;
if(!fg)
{
register int op,num,x; io >> op >> num >> x;
if(!op)
{
++n;
if(num == 1) add(x,n),add(n,x);
else add(n,x);
try(i,2,num)
{
io >> x;
add(n,x);
}
}
else
{
++n;
if(num == 1) add(n,x),add(x,n);
else add(x,n);
try(i,2,num)
{
io >> x;
add(x,n);
}
}
}
else
{
register int x,y; io >> x >> y;
if(x == y) {printf("1\n"); continue;}
memset(vis,0,sizeof(bool) * (n + 1));
printf("%d\n",dfs(x,y));
}
}
return 0;
}
}
signed main() {return xin::main();}