理科卷math·english·chinese·biology·chemistry·physics

一套比一套炸,果然我只会做B卷,虽然我B也很差但没差到这种地步

$math$

题解

看似没法做但总会有突破口

$70\%$

发现和小凯的诱惑很像,于是看$gcd$是否为$1$只要为$1$可以凑齐所有数

$n^2$枚举两两$gcd$

$80\%$

我考试时思路

找到每一个数和$mod$的$gcd$,发现只要是任一$gcd$倍数就可以凑出来,于是枚举每一个数和$mod$的$gcd$,瓶颈在于统计答案

理科卷math·english·chinese·biology·chemistry·physics
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 2222222
ll n,k,cnt=0;
ll a[A],dl[A],ok[A];
ll read(){
    ll x=0,f=1;char c=getchar();
    while(!isdigit(c)){
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return f*x;
}
ll gcd(ll x,ll y){
    if(y==0) return x;
    return gcd(y,x%y);
}
int main(){
    n=read(),k=read();    
    for(ll i=1;i<=n;i++)
        a[i]=read(),dl[++dl[0]]=a[i];
    for(ll i=1;i<=dl[0];i++){
        ll g=gcd(dl[i],k);
        if(g==1){
            printf("%lld\n",k);
            for(ll j=0;j<=k-1;j++){
                printf("%lld ",j);
            }
            return 0;
        }
        else {
            for(ll i=g;i<k;i+=g){
                ok[i]=1;
            }
            ok[0]=1;
        }
    }
    for(ll i=0;i<=k;i++){
        if(ok[i]) cnt++;
    }
    printf("%lld\n",cnt);
    for(ll i=0;i<=k;i++){
    if(ok[i])    printf("%lld ",i);
    }
    printf("\n");
}
View Code

$100\%$

其实从$80\%$我们就应该看出可以找到所有数$gcd$,然后只有为$gcd$倍数才可以凑出来

考试时我连这个都没有想到!

理科卷math·english·chinese·biology·chemistry·physics
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
ll n,k,cnt=0;
ll a[A],dl[A];
ll read(){
    ll f=1,x=0;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return f*x;
}
ll gcd(ll x,ll y){
    if(y==0) return x;
    return gcd(y,x%y);
}
int main(){
    n=read(),k=read();
    for(ll i=1;i<=n;i++){
        a[i]=read();
           while(a[i]<0){
            a[i]+=k;
        }
    }
    ll g=gcd(a[1],a[2]);
    g=gcd(g,k);
    for(ll i=3;i<=n;i++)
        g=gcd(a[i],g);
    for(ll i=0;i<k;i+=g){
        cnt++;
        dl[++dl[0]]=i;
    }
    printf("%lld\n",cnt);
    for(ll i=1;i<=dl[0];i++){
        printf("%lld ",dl[i]);
    }
    printf("\n");
}
View Code

english

题解

破题打了很久从$23$日打到$27$日

然而考试两个人当场$AC$

思路还算比较简单,然而很难打,不用说了我码力太弱

$ans1$还算比较简单,和学数数那个题很像,

我们找到以每一个值为最大值的最左$l$,最右$r$

设当前值位置为$now$

那么因为是异或,造成贡献的只有$now-l$中与$r-now$中二进制位相反的

设$0[x][j]$表示$1--x$中第$j$位为$0$数有多少个(这是前缀和)

类似设$1[x][j]$表示$1--x$中第$j$位为$1$数有多少个

那么$now$贡献就为$\sum\limits_{j=1}^{j<=最高位} (0[now][j]-0[l-1][j])*(1[r][j]-1[now-1][j])+(1[now][j]-1[l-1][j])*(0[r][j]-0[now-1][j])$

然后问题又转化为了找到以每一个值为最大值的最左$l$,最右$r$

这里我还是用的我的老方法(愚蠢至极)

void pre(ll l,ll r,ll now,ll nowmax){
    if(l>r) return ;
    lef[now]=l,rig[now]=r;
    if(l==r) {
        len[now]=r-l+1;
        return ;
    }
    maxn=-1,ida=0;
    if(l<=now-1){    
        seg_max(1,l,now-1);
        pre(l,now-1,ida,maxn);
    }
    maxn=-1,ida=0;
    if(now+1<=r){
        seg_max(1,now+1,r);
        pre(now+1,r,ida,maxn);
    }
}

二分套线段树

复杂度玄学说是$n*{log(n)^2}$然而实际跑起来只比单调栈慢$400ms$,学数数还比单调栈快

上一篇:flutter2.0 环境搭建(window环境下Mac自行查看官网即可)


下一篇:3.17jsp