zoukankan      html  css  js  c++  java
  • AtCoder Beginner Contest 162

    传送门

    A - Lucky 7

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main() {
        int n;
        scanf("%d",&n);
        bool f=false;
        while(n) {
            if(n%10==7) f=true;
            n/=10;
        }
        printf("%s
    ",f?"Yes":"No");
        return 0;
    }
    A.cpp

    B - FizzBuzz Sum

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main() {
        int n;
        scanf("%d",&n);
        ll ans=0;
        for(int i=1;i<=n;i++) {
            if(i%3==0||i%5==0) continue;
            ans+=i;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    B.cpp

    C - Sum of gcd of Tuples (Easy)

    题意:$sum_{a=1}^{K} sum_{b=1}^{K} sum_{c=1}^{K} gcd(a,b,c)$

    数据范围:$1 leq K leq 200$

    题解:K比较小,暴力即可。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main() {
        int n;
        scanf("%d",&n);
        ll ans=0;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                for(int k=1;k<=n;k++) {
                    ans+=__gcd(__gcd(i,j),k);
                }
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    C.cpp

     D - RGB Triplets

    题意:给一个长度为N的字符串S,只包含'R','B','G'。求有多少个三元组$(i,j,k)(1 leq i <j<k leq N)$满足$S_{i} eq S_{j},S_{i}  eq S_{k},S_{j}  eq S_{k}, j-i eq k-j$。

    数据范围:$1leq N leq 4000$

    题解:先将满足$S_{i}  eq S_{j},S_{i}  eq S_{k},S_{j}  eq S_{k}$的算出来,在减去$j-i =k-j$的数目。

    总的显然等于num(R)*num(B)*num(G),然后枚举两个端点,判断第三个端点是不是不同于这个两个端点的颜色。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=4e3+5;
    char s[N];
    int main() {
        int n;
        scanf("%d%s",&n,s);
        int a=0,b=0,c=0;
        for(int i=0;i<n;i++) {
            if(s[i]=='R') a++;
            if(s[i]=='G') b++;
            if(s[i]=='B') c++;
        }
        ll ans=1LL*a*b*c;
        for(int i=0;i<n;i++) {
            for(int j=i+1;j<n;j++) {
                if(s[i]==s[j]) continue;
                if(2*j-i<n&&s[i]!=s[2*j-i]&&s[j]!=s[2*j-i]) ans--;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    D.cpp

     E - Sum of gcd of Tuples (Hard)

    题意:$sum_{a_{1}=1}^{K} sum_{a_{2}=1}^{K}...sum_{a_{N}=1}^{K} gcd(a_{1},a_{2},...,a_{N})$(mod 1e9+7)

    数据范围:$2 leq N leq 10^{5},1 leq K leq 10^{5}$

    题解:

    做法0.比赛中写的莫比乌斯反演,化简过程:

    $Ans=sum_{a_{1}=1}^{K} sum_{a_{2}=1}^{K}...sum_{a_{N}=1}^{K} gcd(a_{1},a_{2},...,a_{N})$

    $=sum_{i=1}^{K}sum_{a_{1}=1}^{K} sum_{a_{2}=1}^{K}...sum_{a_{N}=1}^{K} i[gcd(a_{1},a_{2},...,a_{N})==i]$

    $=sum_{i=1}^{K}sum_{a_{1}=1}^{lfloor frac{K}{i} floor} sum_{a_{2}=1}^{lfloor frac{K}{i} floor}...sum_{a_{N}=1}^{lfloor frac{K}{i} floor} i[gcd(a_{1},a_{2},...,a_{N})==1]$

    $=sum_{i=1}^{K}sum_{a_{1}=1}^{lfloor frac{K}{i} floor} sum_{a_{2}=1}^{lfloor frac{K}{i} floor}...sum_{a_{N}=1}^{lfloor frac{K}{i} floor} i sum_{d=1}^{lfloor frac{K}{i} floor} mu(d)  lfloor frac{d}{a_{1}} floor  lfloor frac{d}{a_{2}} floor ... lfloor frac{d}{a_{N}} floor$

    $=sum_{i=1}^{K} i sum_{d=1}^{lfloor frac{K}{i} floor} mu(d) sum_{a_{1}=1}^{lfloor frac{K}{id} floor} sum_{a_{2}=1}^{lfloor frac{K}{id} floor}...sum_{a_{N}=1}^{lfloor frac{K}{id} floor} 1$

    $=sum_{i=1}^{K} i sum_{d=1}^{lfloor frac{K}{i} floor} mu(d)  lfloor frac{K}{id} floor^{N}$

    $=sum_{T=1}^{K} lfloor frac{K}{T} floor^{N} sum_{d|T} mu(d) ast {lfloor frac{T}{d} floor} (T=id)$

    $=sum_{T=1}^{K} lfloor frac{K}{T} floor^{N} phi(T)$

    由于K不大,预处理欧拉函数,直接遍历即可。K大的话,整除分块加杜教筛(雾。

    做法1.看了下官方题解:定义f[i]代表gcd为i的个数,递推关系式:$f[i]={lfloor frac{K}{i} floor}^{N}-sum_{j>i,i|j}f[j]$。

    双重循环即可,里面那层循环的复杂度总和是个调和级数,log级别的。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    const int MD=1e9+7;
    int pri[N],tot,phi[N];
    bool p[N];
    void init() {
        p[1]=true,phi[1]=1;
        for(int i=2;i<N;i++) {
            if(!p[i]) pri[++tot]=i,phi[i]=i-1;
            for(int j=1;j<=tot&&i*pri[j]<N;j++) {
                p[i*pri[j]]=true;
                if(i%pri[j]==0) {
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
                else phi[i*pri[j]]=phi[i]*(pri[j]-1);
            }
        }
    }
    int quick_pow(int x,int y) {
        int ans=1;
        while(y) {
            if(y&1) ans=1LL*ans*x%MD;
            y>>=1;
            x=1LL*x*x%MD;
        }
        return ans;
    }
    void add(int &x,int y) {
        x+=y;
        if(x>=MD) x-=MD;
    }
    int main() {
        init();
        int n,k,ans=0;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=k;i++) {
            add(ans,1LL*quick_pow(k/i,n)*phi[i]%MD);
        }
        printf("%d
    ",ans);
        return 0;
    }
    E_0.cpp
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    const int MD=1e9+7;
    int f[N];
    int quick_pow(int x,int y) {
        int ans=1;
        while(y) {
            if(y&1) ans=1LL*ans*x%MD;
            y>>=1;
            x=1LL*x*x%MD;
        }
        return ans;
    }
    void add(int &x,int y) {
        x+=y;
        if(x>=MD) x-=MD;
        if(x<0) x+=MD;
    }
    int main() {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=k;i>=1;i--) {
            f[i]=quick_pow(k/i,n);
            for(int j=2*i;j<=k;j+=i) {
                add(f[i],-f[j]);
            }
        }
        int ans=0;
        for(int i=1;i<=k;i++) {
            add(ans,1LL*f[i]*i%MD);
        }
        printf("%d
    ",ans);
        return 0;
    }
    E_1.cpp

    F - Select Half

    题意:给一个长度为N的序列A,要求选$lfloor frac{N}{2} floor$个数,且下标互不相邻,最大化它们的总和。

    数据范围:$2 leq N leq 2 imes 10^{5}$

    题解:对于选的数的下标,$B_{1},B_{2}....,B_{lfloor frac{N}{2} floor}$,可以发现$sum _{i=2}^{lfloor frac{N}{2} floor}B_{i}-B_{i-1}-2 leq 2$。

    因此定义f[i][j]代表选第1~i里面的数(必选第个i数),前面多空了j的最大值。

    $left{ 
    egin{array}{**lr**} 
    f[i][0]=f[i-2][0]+a[i]\ 
    f[i][1]=max(f[i-2][1],f[i-3][0])+a[i]\ 
    f[i][2]=max(f[i-2][2],f[i-3][1],f[i-4][0])+a[i]
    end{array} 
    ight. $

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2e5+5;
    int a[N];
    ll f[N][3];
    int main() {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++) {
            for(int j=0;j<3;j++) {
                f[i][j]=-1e18;
            }
        }
        for(int i=1;i<=3;i++) {
            f[i][i-1]=a[i];
        }
        f[3][0]=a[1]+a[3];
        for(int i=4;i<=n;i++) {
            f[i][0]=f[i-2][0]+a[i];
            f[i][1]=max(f[i-2][1],f[i-3][0])+a[i];
            f[i][2]=max(f[i-2][2],f[i-3][1])+a[i];
            if(i>4) f[i][2]=max(f[i][2],f[i-4][0]+a[i]);
        }
        ll ans;
        if(n&1) ans=max(f[n][2],max(f[n-1][1],f[n-2][0]));
        else ans=max(f[n][1],f[n-1][0]);
        printf("%lld
    ",ans);
        return 0;
    }
    F.cpp
  • 相关阅读:
    Linux内核学习第五周 系统调用
    Linux内核学习第三周 Linux启动过程分析
    WebStorm快捷键大全
    PAT乙级-1056. 组合数的和(15)
    PAT乙级-1043. 输出PATest(20)
    PAT乙级-1021.个位数统计(15)
    PAT乙级-1036.跟奥巴马一起编程(15)
    学习笔记-C++ STL iterator与对指针的理解-20170618
    学习笔记-Little Tips_day20170615-" " and ' '
    HTML5离线存储和本地缓存
  • 原文地址:https://www.cnblogs.com/zdragon1104/p/12688051.html
Copyright © 2011-2022 走看看