AtCoder Beginner Contest 162 题解

A. Lucky 7

  签到。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}

int main(){
    int n=read();
    while(n){
        if(n%10==7){
            puts("Yes");
            return 0;
        }
        n/=10;
    }
    puts("No");

    return 0;
}
View Code

B. FizzBuzz Sum

  签到*2。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}


int main(){
    int n=read();
    LL ans=0;
    for(int i=1;i<=n;++i){
        if(i%3==0||i%5==0){
            continue;
        }
        else{
            ans+=i;
        }
    }

    cout<<ans;

    return 0;
}
View Code

 

C. 给一个上界K,求三个数分别在这三个区间[1-K]内取值时,其gcd之和。

  这个题数据能很轻松出到5000,O(n^2logn)做完,给出5000的做法。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}

int cnt[5005];

int main(){
    int n=read();
    LL ans=0;

    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            int t=__gcd(i,j);
            ++cnt[t];
        }
    }

    for(int i=1;i<=n;++i){
        for(int j=1;j<=5000;++j){
            if(cnt[j]){
                ans+=1ll*cnt[j]*__gcd(j,i);
            }
        }
    }

    cout<<ans;

    return 0;
}
View Code

D. 给一个字符串,统计三元组(i,j,k)(i<j<k)。其下标对应的字母不同,且三元组不成等差数列。

  枚举两个,二分第三个,剔掉成等差数列的情况。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}

vector<int> p[3];

char s[4005];

int main(){
    int n=read();
    scanf("%s", s+1);

    vector<char> t;
    t.PB('R');
    t.PB('G');
    t.PB('B');

    for(int i=1;i<=n;++i){
        if(s[i]=='R')p[0].PB(i);
        if(s[i]=='G')p[1].PB(i);
        if(s[i]=='B')p[2].PB(i);
    }

    LL ans=0;

    for(int i=1;i<=n;++i){
        for(int j=i+1;j<=n;++j){
            if(s[i]!=s[j]){
                for(int k=0;k<=2;++k){
                    if(t[k]!=s[i]&&t[k]!=s[j]){
                        int num=p[k].end()-lower_bound(p[k].begin(),p[k].end(),j);
                        ans+=num;
                        int pos=lower_bound(p[k].begin(),p[k].end(),j+j-i)-p[k].begin();
                        if(pos<SZ(p[k])&&p[k][pos]==j+j-i)--ans;
                    }
                }
            }
        }
    }

    cout<<ans;

    return 0;
}
View Code

E. 现在给N个数,每个数的取值在1-K之间,求它们的gcd之和。

  套路反演入门题,不会的可以先戳莫比乌斯反演

  具体做法就是先枚举gcd,然后反演成带mu函数的式子(其实就是套公式,原理是mu函数的一个性质)。预处理出mu函数前缀和之后,对于gcd的每一个取值,数论分块,快速幂即可。

  (当然,这都是属于吃撑了的做法,真正快速的做法是欧拉反演,一步到位。但由于本人考试时,忘记欧拉的筛子咋写了,就写了个mu的。

  最外层可以再分个块,这样复杂度就变成了O(N*logn)。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}

int powmod(int x, int y){
    int res=1;
    while(y){
        if(y&1)
            res=1ll*res*x%MOD;
        x=1ll*x*x%MOD;
        y>>=1;
    }
    return res;
}

int mu[MAXN];
int Prime[MAXN],isNot[MAXN],tol;

void get_mu(int n){
    mu[1]=1;
    for(int i=2;i<=n;++i){
        if(!isNot[i]){
            Prime[++tol]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=tol;++j){
            if(1ll*i*Prime[j]>n)break;
            isNot[i*Prime[j]]=1;
            mu[i*Prime[j]]=-mu[i];
            if(i%Prime[j]==0){
                mu[i*Prime[j]]=0;
                break;
            }
        }
    }

    for(int i=1;i<=n;++i){
        mu[i]+=mu[i-1];
    }
}

int main(){
    int n=read();
    int k=read();

    get_mu(100005);

    LL ans=0;
    for(int i=1;i<=k;++i){
        LL sum=0;
        for(int l=1,r;l<=k/i;l=r+1){
            r=(k/i)/((k/i)/l);
            sum+=1ll*(mu[r]-mu[l-1])*powmod((k/i)/l,n);
            sum%=MOD;
        }
        ans+=i*sum;
        ans%=MOD;
    }

    ans=(ans%MOD+MOD)%MOD;
    cout<<ans;

    return 0;
}
View Code

F. 给一个长度为n序列,选择n/2个数,使得其和最大。

  我就要开二维数组你能秒我?开不下就用map开第二维。按照题意模拟即可,一个关键剪枝加上之后就能轻松通过。

  我的分析应应该是,空白的个数不能超过(n+1)/2个,且每一个之间距离相差不能超过1。这直接导致解的空间不会太大,就水过去了,复杂度就很玄学(我不会。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline LL read(){
    LL res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

const LL inf = (LL)1e18;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T a, T b){if(b>a)a=b;}

LL a[MAXN], n;
map<int,long long> H[MAXN];

LL dfs(int idx, int cnt){
    if(idx>=n+1){
        if(cnt==n/2)return 0;
        else return -inf;
    }

    if(H[idx].count(cnt))return H[idx][cnt];

    if((cnt+(n-idx+2)/2)<n/2)return -inf;

    return H[idx][cnt]=max(dfs(idx+1,cnt),dfs(idx+2,cnt+1)+a[idx]);
}

int main(){
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();

    cout<<dfs(1,0);

    return 0;
}
View Code

 

 

  

posted @ 2020-04-13 11:51  John_Ran  阅读(280)  评论(0编辑  收藏  举报