AtCoder Beginner Contest 162

傳送門c++

A - Lucky 7ide

#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\n",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\n",ans);
    return 0;
}
B.cpp

C - Sum of gcd of Tuples (Easy)ui

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

數據範圍:$1 \leq K \leq 200$code

題解:K比較小,暴力便可。blog

#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\n",ans);
    return 0;
}
C.cpp

 D - RGB Tripletsip

題意:給一個長度爲N的字符串S,只包含'R','B','G'。求有多少個三元組$(i,j,k)(1 \leq i <j<k \leq N)$知足$S_{i} \neq S_{j},S_{i} \neq S_{k},S_{j} \neq S_{k}, j-i \neq k-j$。字符串

數據範圍:$1\leq N \leq 4000$get

題解:先將知足$S_{i} \neq S_{j},S_{i} \neq S_{k},S_{j} \neq 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\n",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}\rfloor} \sum_{a_{2}=1}^{\lfloor \frac{K}{i}\rfloor}...\sum_{a_{N}=1}^{\lfloor \frac{K}{i}\rfloor} i[gcd(a_{1},a_{2},...,a_{N})==1]$

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

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

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

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

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

因爲K不大,預處理歐拉函數,直接遍歷便可。K大的話,整除分塊加杜教篩(霧。

作法1.看了下官方題解:定義f[i]表明gcd爲i的個數,遞推關係式:$f[i]={\lfloor \frac{K}{i}\rfloor}^{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\n",ans);
    return 0;
}
E.cpp_0
#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\n",ans);
    return 0;
}
E.cpp_1

F - Select Half

題意:給一個長度爲N的序列A,要求選$\lfloor \frac{N}{2}\rfloor$個數,且下標互不相鄰,最大化它們的總和。

數據範圍:$2 \leq N \leq 2 \times 10^{5}$

題解:對於選的數的下標,$B_{1},B_{2}....,B_{\lfloor \frac{N}{2}\rfloor}$,能夠發現$\sum _{i=2}^{\lfloor \frac{N}{2}\rfloor}B_{i}-B_{i-1}-2 \leq 2$。

所以定義f[i][j]表明選第1~i裏面的數(必選第個i數),前面多空了j的最大值。

$\left\{ 
\begin{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} 
\right. $

#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\n",ans);
    return 0;
}
F.cpp
相關文章
相關標籤/搜索