8.【2024初三年前集训测试3】
\(\Huge打了一场模拟赛,终于不垫底了。qwq\)
2024初三年前集训测试3
T1夕景昨日
\(90pts\)
- 不好想,一直做到最后了,然后发现过不了样例,发现读假题了 \(\Large qwq\Huge😓😓😓\) 。
题解
- 只要发现规律,就很好做了。当 \(n>20\) (也有人说是 \(n>24\) 时),我们直接输出 \(Yes\) 即可 (
莫名想到某星战) \(n\le20\) 时暴搜完全可过。 - 为什么?因为当 \(n\) 为 \(20\) 时,所有状态和为 \(2^{20}=1048576\) ,但是值域却是 \(1\) ~ \(500000\) 。(或者说当 \(n=25\) 时,总状态有 \(2^{25}=16777216\) 种状态。假设值域开满,那么就有 \(5\times 10^{5}\times 50=25000000\) ),因此在此时状态一定会冲突,于是输出 \(Yes\) 即可。
代码
暴搜打的不好了,应该用函数但没想到怎么打。
#include<bits/stdc++.h>
#define int long long
#define N (10000010)
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48&&c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int a[100010];
map<signed,signed>s;
signed main()
{
init_set();
cin>>n;
if(n>20)puts("Yes"),exit(0);
for(int i(1);i<=n;++i)cin>>a[i];
if(n<=20)
{
if(n==1)puts("No"),exit(0);
if(n==2)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
if(s.find(a[1]*i+a[2]*j)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j];
if(n==3)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k];
if(n==4)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4];
if(n==5)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5];
if(n==6)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
for(int i6(-1);i6<=1;i6+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6];
if(n==7)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
for(int i6(-1);i6<=1;i6+=2)
for(int i7(-1);i7<=1;i7+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7];
if(n==8)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
for(int i6(-1);i6<=1;i6+=2)
for(int i7(-1);i7<=1;i7+=2)
for(int i8(-1);i8<=1;i8+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8];
if(n==9)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
for(int i6(-1);i6<=1;i6+=2)
for(int i7(-1);i7<=1;i7+=2)
for(int i8(-1);i8<=1;i8+=2)
for(int i9(-1);i9<=1;i9+=2)
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8+a[9]*i9)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8+a[9]*i9];
if(n==10)
for(int i(-1);i<=1;i+=2)
for(int j(-1);j<=1;j+=2)
for(int k(-1);k<=1;k+=2)
for(int i4(-1);i4<=1;i4+=2)
for(int i5(-1);i5<=1;i5+=2)
for(int i6(-1);i6<=1;i6+=2)
for(int i7(-1);i7<=1;i7+=2)
for(int i8(-1);i8<=1;i8+=2)
for(int i9(-1);i9<=1;i9+=2)
for(int i10(-1);i10<=1;i10+=2)
{
//cout<<i<<' '<<j<<' '<<k<<' '<<i4<<' '<<i5<<' '<<i6<<' '<<i7<<' '<<i8<<' '<<i9<<' '<<i10<<'\n';
//cout<<a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8+a[9]*i9+a[10]*i10<<'\n';
if(s.find(a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8+a[9]*i9+a[10]*i10)!=s.end())
puts("Yes"),exit(0);
else ++s[a[1]*i+a[2]*j+a[3]*k+a[4]*i4+a[5]*i5+a[6]*i6+a[7]*i7+a[8]*i8+a[9]*i9+a[10]*i10];
}
puts("No"),exit(0);return 0;
}
flush();
return 0;
}
T2透明答案
\((100pts)→(70pts)→30pts\)
- \(7\) 分钟首 \(A\) 但是瞎搞,所以觉得不是正解,手搓 \(1\) 到 \(3\) 的数据,于是大力模 \(2\) 。。。。。。然后30分。 \(\Huge😔😟😩\) 。
- \(30pts\) 输出 \(Bob\) \(70pts\) 输出 \(Ayano\) \(\Huge😂👉😂👉😂👉\)
- 还有,
\(OI\) 赛制滚出 \(OI\)\(\Huge😠😠😠😡😡😡😭😭😭\)
题解
- 由于最优解可能会有不同拿取方式,(
其实是蒟蒻模拟不出来qwq)因此不再模拟。 - 当 \(n=1\) 时, \(Ayano\) 赢, \(n=2\) 时, \(Bob\) 赢 , \(n=3\) 时, \(Ayano\) 赢, \(n=4\) 时, \(Ayano\) 赢, \(n=5\) 时, \(Bob\) 赢, \(n=6\) 时, \(Ayano\) 赢。
代码
#include<bits/stdc++.h>
#define int long long
#define N (1)
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int x,y,xx,yy,a,b,d,sum,ans;
signed main()
{
init_set();
n=read();
if(n%3==1)puts("Ayano");
else if(n%3==2)puts("Bob");
else puts("Ayano");
flush();
return 0;
}
T3界外科学
\(100pts\)
- 不会打,大力打了个暴搜,加了个剪枝,结果首 \(A\) \(\Huge😨😱\) 。赛后被 \(hack\) 了。并且发现数据太水了!!! \(\Huge😅\) 。输出和就 \(AC\) 了。
题解
- 正解:\(meet\) \(in\) \(middle\) 与 \(01Trie\) ,复杂度 \(\large O(2^\frac n2\log(n))\) 。
- 这里不打正解,正解可以去别处看 \(qwq\) 大佬的博客
代码
- 难绷,剪枝把整棵树都剪了,导致随机超大数据下 \(n=100000\) 有时能卡进 \(1000ms\) 。
- 但是通过超多对拍显示(大约 \(50\) 万组),当 \(m\) 极其小时,会被 \(T\) 飞,原因就是剪枝需要更新答案,而 \(m\) 十分小导致更新答案也十分困难,因此会被卡掉。最坏复杂度 \(\Huge O(2^n)\) \(\Huge😥😥😥\) 。
- 但是当价值超大时,比如是 \(m\) 的 \(2^{20}\) 倍时,可能会 \(T\) 飞。因此:
暴力虽好,可不要贪多哦。。。
-
当然十分好的复杂度可以达到 \(O(1)\) (当第一遍剪枝就减掉整棵搜索树(比如所有满足度小于等于 \(0\) )时)。
-
解决方案:当 \(m<=1e4\) 时,完全可以 \(DP\) 解决,而 \(m>1e4\) 时, 就用 \(dfs\) 暴搜。
-
又一解决方案:将价格转为二进制,并将超大的价格删去(价格改为 \(-1\) ,价值改为 \(0\) (其实改价值不重要,之后用 \(sort\) 排序排到最后即可))。并且只当价格大于 \(m\) 且二进制最高位为 \(1\) ,(其实大于 \(m\) 的只有一个的任意一位均可),之后可以再卡掉一些 \(hack\) 数据。
-
再一解决方案,双向搜索(折半搜索( \(meet\) \(in\) \(middle\) )),可惜我不会打,只能打出最慢 \(\Huge O(2^n)\) 的折半搜索(这真的折半了吗?)。
-
最终复杂度 \(\Large O(???)\) 。
-
\(DFS\) _ \(v1\)
#include<bits/stdc++.h>
#define int long long
#define sort stable_sort
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int ans,cnt,Sum[1010];
struct aa{int x,y;}e[1010];
bool cmp(aa a,aa b){return a.y<b.y;}
void dfs(int x,int val,int sum)
{
//++cnt;//计数器
if(x>n){if(val<=m)ans=max(ans,sum);return;}
if(sum+Sum[n]-Sum[x-1]<=ans)return;//剪枝
dfs(x+1,val,sum);
if(sum+Sum[n]-Sum[x-1]<=ans)return;//意义不大,但有用
dfs(x+1,val^e[x].x,sum+e[x].y);
if(val<=m)ans=max(ans,sum);
return;
}
signed main()
{
init_set();
n=read();m=read();
for(int i(1);i<=n;++i)e[i].x=read();
for(int i(1);i<=n;++i)e[i].y=read();
sort(e+1,e+1+n,cmp);
for(int i(1);i<=n;++i)Sum[i]=Sum[i-1]+((e[i].y>0)?e[i].y:0);
dfs(1,0,0);
//write(cnt,' ');
write(ans,' ');
flush();
return 0;
}
- \(DFS\) _ \(hacker\) _ \(v1\)
#include<bits/stdc++.h>
#define int long long
#define N (10000010)
const int MAXN=1ll*2147483647;
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m,ans;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
signed main()
{
init_set();
srand(std::chrono::system_clock::now().time_since_epoch().count());
n=36;m=10000;
cout<<n<<' '<<m<<'\n';//write(n,' ');write(m,'\n');
for(int i(1);i<=n;++i)
if(i<=15)write(((1<<(i+14))),' ');
else write(1,' ');
*IO::o++='\n';
for(int i(1);i<=n;++i)
if(i<=15)write((10000000),' ');
else write(1,' ');
flush();
return 0;
}
直接卡到原形 \(\large 2^n\) 。
- \(DFS\) _ \(v2\)
- 原理是将超级大的价格大于 \(m\) 的最高位并且在所有数中某位二进制唯一的数删除(价值赋值为 \(-1\) ,价格赋值为 \(0\) )。之后排序扔到最后面。
- 将一些重复的价格异或为 \(0\) (如果价值大于 \(0\) ),并将价值累加。
- 因此可以卡掉 \(DFS\) _ \(hacker\) _ \(v1\) ,只需要 \(8191\) 次运算,等于 \(2^{13}-1\) 。
#include<bits/stdc++.h>
#define int long long
#define sort stable_sort
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<26;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<26,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int ans,cnt,Sum[3000000],TLE[50],rer;
int TP[300][50],bit[100],TOP(1<<29);
struct aa{int x,y;}e[3000000];
bool cmp(aa a,aa b){return a.y<b.y;}
bool xcmp(aa a,aa b){return a.x>b.x;}
void dfs(int x,int val,int sum)
{
//++cnt;
if(x>n){if(val<=m)ans=max(ans,sum);return;}
if(sum+Sum[n]-Sum[x-1]<=ans)return;
dfs(x+1,val^e[x].x,sum+e[x].y);
if(sum+Sum[n]-Sum[x-1]<=ans)return;
dfs(x+1,val,sum);
if(val<=m)ans=max(ans,sum);
return;
}
void bits(int x)
{
for(int i(1),pos(1);i<TOP;i<<=1,++pos)
bit[pos]=(i&x)?1:0;
}
void bitt(int x,int p)
{
for(int i(1),pos(1);i<TOP;i<<=1,++pos)
TP[p][pos]+=(i&x)?1:0,TLE[pos]+=(i&x)?1:0;
}
signed main()
{
init_set();
n=read();m=read();
bits(m);
for(int i(1);i<=n;++i)e[i].x=read(),bitt(e[i].x,i);
for(int i(1);i<=n;++i)e[i].y=read();
for(int i(1);i<=n;++i)
{
for(int j(1);j<=29;++j)
if(TLE[j]==1&&(1<<j)>m&&TP[i][j])
{++rer;e[i].x=-1,e[i].y=0;break;}
}
for(int i(1);i<=n;++i)
for(int j(i+1);j<=n;++j)
if(e[i].x==e[j].x&&e[i].x!=-1&&e[i].y>=0&&e[j].y>=0)
{
e[i].x=0,e[j].x=-1,e[i].y+=e[j].y,e[j].y=0;
++rer;
}
sort(e+1,e+1+n,xcmp);
n-=rer;
sort(e+1,e+1+n,cmp);
for(int i(1);i<=n;++i)Sum[i]=Sum[i-1]+((e[i].y>0)?e[i].y:0);
dfs(1,0,0);
//write(cnt,' ');
write(ans,' ');
flush();
return 0;
}
- \(DFS\) _ \(hacker\) _ \(v2\)
#include<bits/stdc++.h>
#define int long long
#define N (10000010)
const int MAXN=1ll*2147483647;
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m,ans;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
signed main()
{
init_set();
srand(std::chrono::system_clock::now().time_since_epoch().count());
n=36;m=10000;
cout<<n<<' '<<m<<'\n';//write(n,' ');write(m,'\n');
for(int i(1);i<=n;++i)
if(i<=15)write(((1<<(i+14))+(1<<(i+13))),' ');
else write(1,' ');
*IO::o++='\n';
for(int i(1);i<=n;++i)
if(i<=15)write((10000000),' ');
else write(1,' ');
flush();
return 0;
}
-
这一版 \(DFS\) _ \(hacker\) 的效果并没有像预想中的那么好, \(DFS\) _ \(v2\) 仍然可以在 \(0.2s\) 内运行。
-
但是将 \(m\) 改成 \(1\) 或 \(0\) , \(i\) 改为 \(i<=27\) 输出 \(((1<<(i+2))+(1<<(i+1)))\) 就有很大效果了。需要运算 \(4294967295\) 次,等于 \(2^{32}-1\) ,已经卡死了 \(qwq\) 。
-
\(DFS\) _ \(v3\)
-
这是最后一版 \(DFS\) ,用上了蒟蒻已知的大多数优化,双向搜索。但是效果并不好,因为在最后计算答案时会退化,并且可能会出错。所以这版烂尾了 \(qwq\) 。
#include<bits/stdc++.h>
#define int long long
#define sort stable_sort
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<26;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<26,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int ans,cnt,Sum[300000],TLE[50],ans2,rer;
int TP[300][50],bit[100],TOP(1<<29);
int ansqwq;
struct aa{int x,y;}e[300000];
vector<aa>qwq,pmp;
bool cmp(aa a,aa b){return a.y<b.y;}
bool gcmp(aa a,aa b){return a.y>b.y;}
bool lcmp(aa a,aa b){return a.x>b.x;}
void dfs(int x,int val,int sum)
{
//++cnt;
if(x>(n>>1)){qwq.push_back({val,sum});if(val<=m)ans=max(ans,sum);return;}
if(sum+Sum[n]-Sum[x-1]<=ans)return;//剪枝
dfs(x+1,val,sum);
if(sum+Sum[n]-Sum[x-1]<=ans)return;//意义不大,但有用
dfs(x+1,val^e[x].x,sum+e[x].y);
return;
}
void dfs2(int x,int val,int sum)
{
//++cnt;
if(x>n){pmp.push_back({val,sum});if(val<=m)ans2=max(ans2,sum);return;}
if(sum+Sum[n]-Sum[x-1]<=ans2)return;
dfs2(x+1,val,sum);
if(sum+Sum[n]-Sum[x-1]<=ans2)return;
dfs2(x+1,val^e[x].x,sum+e[x].y);
return;
}
void dfss()
{
dfs(1,0,0);
dfs2((n>>1)+1,0,0);
}
void bits(int x)
{
for(int i(1),pos(1);i<=TOP;i<<=1,++pos)
bit[pos]=(i&x)?1:0;
}
void bitt(int x,int p)
{
for(int i(1),pos(1);i<=TOP;i<<=1,++pos)
TP[p][pos]+=(i&x)?1:0,TLE[pos]+=(i&x)?1:0;
}
signed main()
{
init_set();
n=read();m=read();
bits(m);
for(int i(1);i<=n;++i)e[i].x=read(),bitt(e[i].x,i);
for(int i(1);i<=n;++i)e[i].y=read();
for(int i(1);i<=n;++i)
for(int j(i+1);j<=n;++j)
if(e[i].x==e[j].x&&e[i].x!=-1&&e[i].y>=0&&e[j].y>=0)
{
e[i].x=0,e[j].x=-1,e[i].y+=e[j].y,e[j].y=0;
++rer;
}
if(rer)sort(e+1,e+1+n,lcmp),n-=rer;
sort(e+1,e+1+n,cmp);
for(int i(1);i<=n;++i)Sum[i]=Sum[i-1]+((e[i].y>0)?e[i].y:0);
dfss();
sort(qwq.begin(),qwq.end(),gcmp);
sort(pmp.begin(),pmp.end(),gcmp);
for(aa i:qwq)
{
for(aa j:pmp)
{
if((i.x^j.x)<=m)
{
ansqwq=max(ansqwq,i.y+j.y);
}
if(ansqwq>=((i.y)*(j.y)))break;
}
if(ansqwq>=((i.y)*(pmp.front().y)))break;
}
//write(cnt,' ');
write(ansqwq,'\n');
flush();
return 0;
}
- 刚才的 \(hack\) 跑了 \(30\) 秒,加上这句可以少跑 \(15\) 秒。
- 也许双向搜索本身并没有多占时间,但是后面最劣 \(O(cnt^2)\) 的复杂度还是望而生畏。。。
- 双向搜索一共搜索 \(196606\) 次。
- 正确率大约 \(85\%\) 。原因是 \(dfs2\) 中的剪枝是错误的,不可以直接这样剪枝。但是改掉又十分慢。。。
for(int i(29);i;--i)
{
if(bit[i])break;
for(int j(1);j<=n;++j)
{
if(TLE[i]==1&&TP[j][i])
{
++rer;e[i].x=-1,e[i].y=0;
for(int k(1);k<=29;++k)
if(TP[i][k])TP[i][k]=0,--TLE[k];
break;
}
}
}
- 剪枝应该是这个。
void dfs2(int x,int val,int sum)
{
//++cnt;
if(x>n){pmp.push_back({val,sum});if(val<=m)ans2=max(ans2,sum);return;}
if(sum+Sum[n]-Sum[x-1]+Sum[(n>>1)]<=ans2)return;
dfs2(x+1,val,sum);
if(sum+Sum[n]-Sum[x-1]+Sum[(n>>1)]<=ans2)return;
dfs2(x+1,val^e[x].x,sum+e[x].y);
return;
}
-
最后发现 \(DFS\) _ \(2\) 才是最好的。 \(\Huge😥😥😥\) 。
-
附简单 \(hack\) 数据生成器。
#include<bits/stdc++.h>
#define int long long
#define N (10000010)
const int MAXN=1ll*2147483647;
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<25,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
inline signed min(signed x,signed y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline long long min(long long x,long long y){return y&((y-x)>>63)|x&(~(y-x)>>63);}
inline signed max(signed x,signed y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline long long max(long long x,long long y){return x&((y-x)>>63)|y&(~(y-x)>>63);}
inline void swap(signed &x,signed &y){x^=y^=x^=y;}
int n,m,ans;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
signed main()
{
//init_set();
srand(std::chrono::system_clock::now().time_since_epoch().count());
n=36;m=10000;
cout<<n<<' '<<m<<'\n';//write(n,' ');write(m,'\n');
for(int i(1);i<=n;++i){
//if(i<=8)write(((1<<(i+14))),' ');
if(i<=8)cout<<rand()%2000000+2000000<<' ';//write(rand()%2000000+2000000,' ');
else cout<<rand()%10<<' ';//write(rand()%10,' ');
}
cout<<'\n';//*IO::o++='\n';
for(int i(1);i<=n;++i){
//if(i<=8)write((10000000),' ');
if(i<=8) cout<<rand()%1000000+1000000<<' ';//write(rand()%1000000+1000000,' ');
else cout<<rand()%10-3<<' ';//write(rand()%10-3,' ');
}
flush();
return 0;
}
T4回忆补时
\(30pts\)
- 本次模拟赛唯一能够不被成为“
💩”的题。但是还是“💩”(因为打不出来\(\Huge😓😓😓\))。正解:李超线段树。 - 其中 \(30pts\) 暴力枚举 \(O(n^2q)\) 。
- \(60pts\) 维护最值和次值(本来想这么打,但是觉得打了也没什么意义,就没打\(\Huge😤😤😤\))。
题解
- (無)
代码
- (無)
\(\Huge但是打了一场模拟赛,终于不垫底了。qwq\)