NOI Online 2020 Round3 滚粗记

由于上场总结名字叫爆零记,这场就叫做滚粗记吧qwq。
但的确是又滚粗了…
感觉这场题目质量不高,全是一些非常显然的板题。
结果我又被CCF的神仙比赛系统和智障的我给送自闭了。

day -1

2020.5.23 试机
其实我是去试了机的…结果发现有一个奇奇怪怪的滑动验证打不开…
以为明天考试会修复的然后就溜了:)

day 1

看T1…感觉CCF突然变娘心了。
然后发现提交还是有滑动验证…自闭了…
——此处省略关于我如何刷新页面约200次,换了4个浏览器,终于验证成功的事——
此时考试已经过去半个小时…心态崩了…
然后看T2…显然是一个bitset优化矩阵乘法的题目…写完之后发现有点卡…然后开始慌张…于是我又开始水群…结局当然是水了半个小时什么都不知道还白白浪费了时间。于是慌乱之中写了个暴力生成了一组强一些的数据对拍的一下然后就扔了。
看T3…最开始觉得好难的样子…然后仔细分析了一下数据规模发现是个快速子集变换模板题[惊]。这时候还剩下一个半小时,就毫不犹豫的开始写了(其实当时我有怀疑这题 O ( 3 n ) O(3^n) O(3n)能不能过…但我想这题如果这都能过的话那不是放在入门组T3都简单了吗qwq)。写完了之后发现过不了样例,除了个阶乘就过了。
接下来是整场考试最悲剧的时刻:考试结束前5分钟,我突然发现T3卷积必须再多加一维统计加入次数否则则会WA掉,然后我改完之后连样例都没有测就交上去了。
事后测了样例是过了的。
期望得分: 100 + ≈ 100 + 100 = ≈ 300 100+≈100+100=≈300 100+100+100=300

总结

出成绩了…
实际得分: 100 + 20 + 0 = 120 100+20+0=120 100+20+0=120[大哭…]
T2 读入数组忘开long long挂成20分。
T3 常数过大TLE由于我没调整dp值域大小直接0分…
首先这次又去水群了,再加上最开始时的滑动验证,白白浪费1个小时,确实不应该…这一个小时应该认真检查代码错误的。
其次,T2我又犯了我经常会犯的错误,我还是没有吸取教训,有些失望。
当然NOI Online也算是著名的挂题比赛了[大雾](其一是因为它没有大样例,其二是出题人通常挖的坑相当的多),线下考试的时候大样例通常还是比较强的,我也不要过分担心挂题这件事情。但是类似long longREMLE这样的问题是一定要避免的。

题解

T1-水壶(kettle)

相信大家都会做,我就不说了。

T2-魔法值(magic)

其实bitset优化矩阵乘法的方法并不优秀,而且很容易TLE。
我们其实可以先倍增预处理好原矩阵 2 k 2^k 2k次幂的矩阵。
由于答案矩阵是 1 × n 1\times n 1×n的,因此我们合并的时候就只需要 O ( n 2 log ⁡ k ) O(n^2\log k) O(n2logk)即可完成。

T3-优秀子序列(sequence)

O ( 3 k ) O(3^k) O(3k)的方法没什么好说的,跳过。
跟[WC2018]州区划分很类似,但我之前没做过这题
首先让你求 ∑ ϕ ( x ) \sum \phi(x) ϕ(x)没什么特别的含义,换成什么函数都可以。
然后我们用类似[WC2018]州区划分的方法进行子集卷积。
但是原题需要我们求的是无标号方案数。
我们知道无标号方案数 G ( x ) = e F ( x ) G(x)=e^{F(x)} G(x)=eF(x)( F ( x ) F(x) F(x)为有标号方案数)。
这里我们可以直接暴力exp。
复杂度: O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)
有一个巨坑, a i = 0 a_i=0 ai=0需要单独讨论…

代码

T1-kettle

/*Lower_Rating*/
/*NOI Online 3*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define LL long long
#define DB double
#define MOD 1000000007
#define Pr pair
#define X first
#define Y second
#define MAXN 1000000
#define eps 1e-10
#define INF 1000000000
#define inf 100000000000000000LL
#define mem(x,p) memset(x,p,sizeof(x))

LL read(){
  LL x=0,F=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
  return x*F;
}
int add(int a,int b){return (a+b>=MOD)?a+b-MOD:a+b;}
int dec(int a,int b){return (a-b<0)?a-b+MOD:a-b;}
int mul(int a,int b){return 1LL*a*b%MOD;}
int fst_pow(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=mul(res,a);
        a=mul(a,a);
        b>>=1;
    }return res;
}
int inv(int a){return fst_pow(a,MOD-2);}

int n,k,sum[MAXN+5],ans;

int main(){
    freopen("kettle.in","r",stdin);
    freopen("kettle.out","w",stdout);
    n=read(),k=read()+1;
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+read();
    for(int i=1;i<=n-k+1;i++)
    ans=max(ans,sum[i+k-1]-sum[i-1]);
    printf("%d\n",ans);
}

T2-magic

/*Lower_Rating*/
/*NOI Online 3*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define LL long long
#define DB double
#define MOD 1000000007
#define Pr pair
#define X first
#define Y second
#define MAXN 100
#define eps 1e-10
#define INF 1000000000
#define inf 100000000000000000LL
#define mem(x,p) memset(x,p,sizeof(x))

LL read(){
  LL x=0,F=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
  return x*F;
}
int add(int a,int b){return (a+b>=MOD)?a+b-MOD:a+b;}
int dec(int a,int b){return (a-b<0)?a-b+MOD:a-b;}
int mul(int a,int b){return 1LL*a*b%MOD;}
int fst_pow(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=mul(res,a);
        a=mul(a,a);
        b>>=1;
    }return res;
}
int inv(int a){return fst_pow(a,MOD-2);}

int n,m,q;LL f[MAXN+5],g[MAXN+5][MAXN+5];
LL ans;

struct Matrix{
    bitset<MAXN+5> a[MAXN+5];
    void init(){
        for(int i=1;i<=n;i++)a[i].reset();
    }
    Matrix operator*(const Matrix B)const{
        Matrix C;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            if(B.a[j][i])C.a[j]^=a[i];
        return C;
    }
}tmp,B,res;

void fst_pow(LL k){
    res.init();
    for(int i=1;i<=n;i++)res.a[i].set(i);
    while(k){
        if(k&1)res=res*tmp;
        tmp=tmp*tmp,k>>=1;
    }
}
void bute(){
    for(int i=1;i<=n;i++)
    g[0][i]=f[i];;
    for(int i=1;i<=q;i++){
        LL p=read();
        for(int j=1;j<=p;j++)
            for(int t=1;t<=n;t++){
                g[j][t]=0;
                for(int k=1;k<=n;k++)
                if(B.a[t][k])
                g[j][t]^=g[j-1][k];
            }
        printf("%lld\n",g[p][1]);
    }
}

int main(){
	freopen("magic.in","r",stdin);
    freopen("magic.out","w",stdout);
    n=read(),m=read(),q=read();
    for(int i=1;i<=n;i++)f[i]=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read();
        B.a[v].set(u);
        B.a[u].set(v);
    }
    //bute();
    while(q--){
        LL p=read();
        tmp=B;
        fst_pow(p);
        ans=0;
        for(int j=1;j<=n;j++)
        if(res.a[1][j])ans^=f[j];
        printf("%lld\n",ans);
    }
}

T3-sequence

#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define LL long long
#define DB double
#define MAXM 18
#define MAXN 1000000
#define MOD 1000000007
#define mem(x,v) memset(x,v,sizeof(x))

LL read(){
    LL x=0,F=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*F;
}

int add(int x,int y){return (x+y>=MOD)?x+y-MOD:x+y;}
int dec(int x,int y){return (x-y<0)?x-y+MOD:x-y;}
int mul(int x,int y){return (1LL*x*y)%MOD;}
int fst_pow(int x,int y){
    int res=1;
    while(y){
        if(y&1)res=mul(res,x);
        x=mul(x,x),y>>=1;
    }return res;
}

int n,m,cnt,a[MAXN+5],bit[(1<<MAXM)+5],inv[(1<<MAXM)+5],ans,F;
int f[MAXM+1][(1<<MAXM)+1],g[MAXM+1][(1<<MAXM)+1],tmp[(1<<MAXM)+1],A[MAXM+1][(1<<MAXM)+1];

int phi[(1<<MAXM)+5],isp[(1<<MAXM)+5],pri[(1<<MAXM)+5],pcnt;
void prepare(){
    isp[1]=1,phi[1]=1;
    for(int i=2;i<=cnt;i++){
        if(!isp[i])pri[++pcnt]=i,phi[i]=i-1;
        for(int j=1;j<=pcnt&&pri[j]*i<=cnt;j++){
            isp[pri[j]*i]=1;
            if(i%pri[j]==0)phi[pri[j]*i]=phi[i]*pri[j];
            else phi[pri[j]*i]=phi[i]*(pri[j]-1);
        }
    }
    inv[0]=inv[1]=1;
    for(int i=2;i<=cnt;i++)
    inv[i]=mul(MOD-MOD/i,inv[MOD%i]);
}

int lowbit(int x){return x&(-x);}
void FWT(int *d,int len,int x){
    for(register int i=1;i<len;i<<=1)
        for(register int j=0;j<len;j+=(i<<1))
            for(register int k=0;k<i;k++)
            if(x==1)d[i+j+k]=add(d[i+j+k],d[j+k]);
            else d[i+j+k]=dec(d[i+j+k],d[j+k]);
}

void FST(){
    for(int i=0;i<=m;i++)FWT(g[i],cnt,1);
    for(int S=0;S<cnt;S++){
        f[0][S]=1;
        for(int i=1;i<=m;i++){
            int sum=0;
            for(int j=0;j<i;j++)
            f[i][S]=add(f[i][S],mul(mul(j+1,g[j+1][S]),f[i-j-1][S]));
            f[i][S]=mul(f[i][S],inv[i]);
        }
    }
    for(int i=0;i<=m;i++)FWT(f[i],cnt,-1);
}

int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    n=read(),m=MAXM,cnt=(1<<MAXM);
    prepare();
    for(int S=1;S<cnt;S++)bit[S]=bit[S>>1]+(S&1);
    for(int i=1;i<=n;i++){
        a[i]=read();
        g[bit[a[i]]][a[i]]++;
    }
    F=fst_pow(2,g[0][0]),g[0][0]=0;
    FST();
    for(int S=0;S<cnt;S++)
    ans=add(ans,mul(phi[S+1],f[bit[S]][S]));
    printf("%d",mul(ans,F));
}

你可能感兴趣的:(赛后总结)