NOIOL #2 爆零记
阅读原文时间:2023年07月08日阅读:1

没有假是真的爆零了,原因:万恶的文操。不管怎样写份题解吧。

T1:

做题经历:看了下题发现:不是 edu 的原题吗?兴奋地拿出赛中写的程序搞上去。

大约比赛开始 30min 后开始发现 \(k\) 可以等于 \(1\),然后急忙特判了个 \(1\) 就没了。

预计得分(不计文操):100

题解:

由于 \(\operatorname{lcm}(p1,p2) \le 10^{20}\),所以我们可以将带子的长度看做 \(\infty\)。

不妨设 \(p_1<p_2\)。

显然最长的一段连续的相同的色块只可能是红色。

那么我们肯定要贪心的将公共部分染成蓝色。

这样题目就转化为:是否存在整数 \(a\) 使得 \([ap_2+1,(a+1)p_2-1]\) 中 \(p_1\) 的个数 \(\geq k\)

由于 \(p1\) 和 \(p2\) 不一定互质,可以将它们都除以它们的 \(\gcd\)。

根据扩展欧几里得,一定存在正整数 \(x,y\) 使得 \(xp_1-yp_2=1\)。那么我们需检查 \([yp_2+1,(y+1)p_2-1]\) 中是否有 \(\geq k\) 个 \(p_1\) 的倍数。

这可以用 \(\texttt{exgcd}\) 求出,不过进一步发现这里的 \(x,y\) 是什么不重要,因为 \(yp_2+1\) 已经是一个 \(p_2\) 的倍数,我们只需比较 \((x+k-1)p_1+1\) 与 \((y+1)p_2-1\) 的关系,即 \((k-1)p_1+2\) 与 \(p_2\) 的关系。如果 \((k-1)p_1+2 \leq p_2\),答案为 No;反之答案为 Yes。

注意判 \(k=1\)

//Coded by tzc_wk
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
*/
#include <bits/stdc++.h>
using namespace std;
#define fi            first
#define se            second
#define fz(i,a,b)    for(int i=a;i<=b;i++)
#define fd(i,a,b)    for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a)        a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a)    memset(a,0,sizeof(a))
#define fill1(a)    memset(a,-1,sizeof(a))
#define fillbig(a)    memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a)        (1ll<<(a))
#define maskx(a,x)    ((a)<<(x))
#define _bit(a,x)    (((a)>>(x))&1)
#define _sz(a)        ((int)(a).size())
#define filei(a)    freopen(a,"r",stdin);
#define fileo(a)    freopen(a,"w",stdout);
#define fileio(a)     freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x)        putchar(x)
#define eoln        put('\n')
#define space        put(' ')
#define y1            y_chenxiaoyan_1
#define y0            y_chenxiaoyan_0
#define int long long
typedef pair<int,int> pii;
inline int read(){
    int x=0,neg=1;char c=getchar();
    while(!isdigit(c)){
        if(c=='-')  neg=-1;
        c=getchar();
    }
    while(isdigit(c))   x=x*10+c-'0',c=getchar();
    return x*neg;
}
inline void print(int x){
    if(x<0){
        putchar('-');
        print(abs(x));
        return;
    }
    if(x<=9)    putchar(x+'0');
    else{
        print(x/10);
        putchar(x%10+'0');
    }
}
inline int qpow(int x,int e,int _MOD){
    int ans=1;
    while(e){
        if(e&1) ans=ans*x%_MOD;
        x=x*x%_MOD;
        e>>=1;
    }
    return ans;
}
signed main(){
    int T=read();
    while(T--){
        int x=read(),y=read(),z=read();
        if(z==1){
            puts("No");
            continue;
        }
        int gcd=__gcd(x,y);
        x/=gcd;y/=gcd;
//        cout<<x<<" "<<y<<endl;
        if(x*(z-1)+2<=y||y*(z-1)+2<=x)  puts("No");
        else                            puts("Yes");
    }
    return 0;
}
/*
3 4 6 8 9 12
*/

T2:

做题经历:50 分做法太水不过了,不能满足我的要求,因此一直在想满分做法。

想了 \(~25\) min,想到了一个线段树做法,就开始写。

写+调大约共用时 \(30\) 分钟。然后造极端数据发现跑了 3000ms /fad

疯狂卡常,耗在卡常上的时间堪比写程序的时间。register、inline 什么的全用上了,然后也没有发现明显的优化效果。

据说是取模的常数大?

预计得分(不计文操):70~100(不知道 CCF 数据毒不毒)

题解:

首先值域是 \(10^9\) 就暗示着需要离散化。

我们枚举左端点 \(l\),考虑当左端点为 \(l\) 的区间对答案的贡献,把这些贡献全部加在一起就是最终的答案。

题目就简化为求 \(\sum\limits_{i=l}^n f(l,i)^2\)

对于 \([l,n]\) 中出现过的 \(x\),我们找出它在 \([l,n]\) 中出现最靠左的位置 \(pos_x\)。我们记 \(t_i\) 为 \(f(l,i)\) 的值。倒着循环 \(l\),考虑左端点从 \(l+1\) 变为 \(l\) 的影响,假设原来的 \(pos_{a_l}\) 为 \(l'\),那么会发生以下两件事:

  1. \(pos_{a_l}\) 会变为 \(l\)

  2. \(t_l,t_{l+1},\dots,t_{l'-1}\) 的值将全部加 \(1\)。因为 \(a_l\) 这个数在 \([l+1,l],[l+1,l+1],\dots,[l+1,l'-1]\) 中没有出现过,而在 \([l,l],[l,l+1],\dots,[l,l'-1]\) 出现过了。

    那么现在就变成了下面的问题:

  • 区间加某个数

  • 求区间中所有数平方的和

    这个可以用线段树来实现。考虑区间加上某个数 \(k\),那么平方和变为:

\[(a_l+k)^2+(a_{l+1}+k)^2+\dots+(a_r+k)^2
\]

\[=a_l^2+2ka_l+k^2+a_{l+1}^2+2ka_{l+1}+k^2+\dots+a_r^2+2ka_r+k^2
\]

\[=(a_l^2+a_{l+1}^2+\dots+a_r^2)+2k(a_l+a_{l+1}+\dots+a_r)+(r-l+1) \times k^2
\]

维护区间平方和和区间和就可以做到 \(\mathcal O(1)\) 更新了。

//Coded by tzc_wk
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
*/
#include <bits/stdc++.h>
using namespace std;
#define fi            first
#define se            second
#define fz(i,a,b)    for(register int i=a;i<=b;i++)
#define fd(i,a,b)    for(register int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a)        a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a)    memset(a,0,sizeof(a))
#define fill1(a)    memset(a,-1,sizeof(a))
#define fillbig(a)    memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a)        (1ll<<(a))
#define maskx(a,x)    ((a)<<(x))
#define _bit(a,x)    (((a)>>(x))&1)
#define _sz(a)        ((int)(a).size())
#define filei(a)    freopen(a,"r",stdin);
#define fileo(a)    freopen(a,"w",stdout);
#define fileio(a)     freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x)        putchar(x)
#define eoln        put('\n')
#define space        put(' ')
#define y1            y_chenxiaoyan_1
#define y0            y_chenxiaoyan_0
#define int long long
typedef pair<int,int> pii;
inline int read(){
    int x=0,neg=1;char c=getchar();
    while(!isdigit(c)){
        if(c=='-')  neg=-1;
        c=getchar();
    }
    while(isdigit(c))   x=x*10+c-'0',c=getchar();
    return x*neg;
}
inline void print(int x){
    if(x<0){
        putchar('-');
        print(abs(x));
        return;
    }
    if(x<=9)    putchar(x+'0');
    else{
        print(x/10);
        putchar(x%10+'0');
    }
}
inline int qpow(int x,int e,int _MOD){
    int ans=1;
    while(e){
        if(e&1) ans=ans*x%_MOD;
        x=x*x%_MOD;
        e>>=1;
    }
    return ans;
}
const int MOD=1e9+7;
int n,a[1000005],key[1000005],hs[1000005],cnt=0;
struct node{
    int l,r;
    int sum,sqr;
    int lz;
} s[1000005<<2];
inline void build(int k,int l,int r){
    s[k].l=l;s[k].r=r;
    if(l==r)    return;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
inline void pushup(int k){
    s[k].sqr=s[k<<1].sqr+s[k<<1|1].sqr;
    if(s[k].sqr>MOD)    s[k].sqr-=MOD;
    s[k].sum=s[k<<1].sum+s[k<<1|1].sum;
    if(s[k].sum>MOD)    s[k].sum-=MOD;
}
inline void pushdown(int k){
    if(!s[k].lz)    return;
    s[k<<1].sqr=(s[k<<1].sqr+2*s[k].lz*s[k<<1].sum+(s[k<<1].r-s[k<<1].l+1)*s[k].lz*s[k].lz)%MOD;
    s[k<<1].sum=(s[k<<1].sum+(s[k<<1].r-s[k<<1].l+1)*s[k].lz)%MOD;
    s[k<<1].lz+=s[k].lz;
    s[k<<1|1].sqr=(s[k<<1|1].sqr+2*s[k].lz*s[k<<1|1].sum+(s[k<<1|1].r-s[k<<1|1].l+1)*s[k].lz*s[k].lz)%MOD;
    s[k<<1|1].sum=(s[k<<1|1].sum+(s[k<<1|1].r-s[k<<1|1].l+1)*s[k].lz)%MOD;
    s[k<<1|1].lz+=s[k].lz;
    s[k].lz=0;
}
inline void modify(int k,int l,int r,int x){
    if(l<=s[k].l&&s[k].r<=r){
        s[k].sqr=(s[k].sqr+2*x*s[k].sum+(s[k].r-s[k].l+1)*x*x)%MOD;
        s[k].sum=(s[k].sum+(s[k].r-s[k].l+1)*x)%MOD;
        s[k].lz+=x;
        return;
    }
    pushdown(k);
    int mid=(s[k].l+s[k].r)>>1;
    if(r<=mid)      modify(k<<1,l,r,x);
    else if(l>mid)  modify(k<<1|1,l,r,x);
    else            modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
    pushup(k);
}
inline int query(int k,int l,int r){
    if(l<=s[k].l&&s[k].r<=r){
        return s[k].sqr;
    }
    pushdown(k);
    int mid=(s[k].l+s[k].r)>>1;
    if(r<=mid)      return query(k<<1,l,r);
    else if(l>mid)  return query(k<<1|1,l,r);
    else            return (query(k<<1,l,mid)+query(k<<1|1,mid+1,r))%MOD;
}
int lst[1000005];
signed main(){
    n=read();
    fz(i,1,n)   a[i]=read();
    fz(i,1,n)   key[i]=a[i];
    sort(key+1,key+n+1);
    fz(i,1,n)   if(key[i]!=key[i-1])    hs[++cnt]=key[i];
    fz(i,1,n)   a[i]=lower_bound(hs+1,hs+cnt+1,a[i])-hs;
    fz(i,1,cnt) lst[i]=n+1;
    build(1,1,n);
    int ans=0;
    fd(i,n,1){
        modify(1,i,lst[a[i]]-1,1);
        ans=(ans+query(1,i,n))%MOD;
//        cout<<query(1,i,n)<<endl;
        lst[a[i]]=i;
    }
    cout<<ans<<endl;
    return 0;
}
/*
6
1 2 1 3 2 1
*/

T3:

做题经历:由于做完 T2 之后划了 \(40\) 分钟的水,时间不太够了。再加上一开始 ix35 神仙还发了个贴说看不懂样例(雾,信就是 ix35 在假,因为他不久就狂切掉了这道题),让我以为是道毒瘤题就没往下写。

因此花了 \(20\) 分钟写了个暴力 \(40\) 分程序就走人了。

赛后看了下题解发现思路其实也没那么超纲。

不管怎样赛后再填吧。

赛后 \(30\) 分钟心情还是蛮好的。

然后发现要文操。

呃呃呃呃呃……什么东西。

最后,爆零选手 ET2006 衷心提醒大家:

忘文件操作,爆零两行泪。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器