AtCoder Beginner Contest 162 题解
签到。
#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; }
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; }
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; }
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; }
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; }
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; }