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\)
image

image

image

posted @ 2024-02-16 18:51  minecraft114514  阅读(22)  评论(0编辑  收藏  举报