Educational Codeforces Round 12
665A - Buses Between Cities 20171129
奇奇怪怪的小数学题...推推式子就好了,边界情况比较蛋疼
#include<stdlib.h> #include<stdio.h> #include<math.h> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int a,ta,b,tb,h,m,t; int main() { scanf("%d%d%d%d",&a,&ta,&b,&tb);a*=2,ta*=2,b*=2,tb*=2; scanf("%d:%d",&h,&m),t=60*h+m-300;t*=2; printf("%d\n",min(t+ta-1,2278)/b-(t-tb+1<=-1?-b:t-tb+1)/b); return 0; }
665B - Shopping 20171129
按题意模拟即可
#include<stdlib.h> #include<stdio.h> #include<math.h> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m,x,k,a,p[101],ans; int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++) scanf("%d",&p[i]); for(int i=1;i<=n*m;i++) { scanf("%d",&a); for(int j=1;j<=k;j++) if(p[j]==a)x=j; ans+=x; p[0]=p[x]; for(int j=x;j>=1;j--) p[j]=p[j-1]; } return printf("%d\n",ans),0; }
665C - Simple Strings 20171129
每次判断当前字符是否与前一个相同,若相同则改变当前字符使其满足条件
#include<stdlib.h> #include<stdio.h> #include<math.h> #include<cstring> #include<iostream> #include<algorithm> using namespace std; string s; char rua(int i) { for(char x='a';x;x++) if(s[i-1]!=x && s[i+1]!=x)return x; } int main() { cin>>s; for(int i=1;i<s.size();i++) if(s[i]==s[i-1])s[i]=rua(i); cout<<s<<endl;return 0; }
665D - Simple Subset 20180816
两个正整数相加为质数的情况:两个1、一奇数一偶数
可以发现如果第二种情况出现了,除非那个奇数是1,否则再加入任意一个数都会使得出现两个数的和是一个大于2的偶数
所以最优解只可能是:若干个1外加一个数x满足x+1是质数;或者是一奇数一偶数相加为质数。若以上两种情况均不存在,输出任意一个数即可(最坏情况)
#include<bits/stdc++.h> using namespace std; #define M 2000001 #define N 1001 int n,c,cnt,a[N],f[N]; bool x[M]; void pretype() { for(int i=2;i<M;i++) if(!x[i]) for(int j=2*i;j<M;j+=i) x[j]=true; } void print() { printf("%d\n",cnt);for(int i=1;i<=cnt;i++)printf("%d%c",f[i],i<cnt?' ':'\n'); } int main() { pretype(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) if(a[i]==1)f[++cnt]=1; for(int i=1;i<=n;i++) if(a[i]>1 && !x[a[i]+1]) {f[++cnt]=a[i];break;} if(cnt>2)return print(),0; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(!x[a[i]+a[j]]) return printf("2\n%d %d\n",a[i],a[j]),0; return printf("1\n%d\n",a[1]),0; }
665E - Beautiful Subarrays 20190403
字典树的经典应用,考虑数组的前缀异或和,问题变为有多少对数的异或和\(\ge k\)。依次插入每个数时同时询问字典树中有多少数和当前异或的结果满足条件即可,记得把一开始的0加进去
#include<bits/stdc++.h> using namespace std; #define N 1000001 #define LL long long int n,k,x,cnt=1,a[N],s[N*35],t[N*35][2];LL ans; int main() { scanf("%d%d",&n,&k); for(LL i=1;i<=n;i++)scanf("%d",&a[i]),a[i]^=a[i-1]; for(LL i=0;i<=n;i++) { s[x=1]++; for(LL j=30;j>=0;j--) { bool y=(a[i]>>j)&1; if(!t[x][y])t[x][y]=++cnt; x=t[x][y],s[x]++; } x=1; for(LL j=30;j>=0;j--) { bool y=((k^a[i])>>j)&1; if(!((k>>j)&1))ans+=s[t[x][y^1]]; if(t[x][y])x=t[x][y]; else{x=0;break;} } ans+=s[x]; } return printf("%I64d\n",ans),0; }
665F - Four Divisors 20190403
注意到如果一个数的约数个数恰好为4,则其一定是一个质数的三次方或者是两不同质数的乘积。前者的贡献可以线性筛预处理得出,后者则是min_25筛的经典应用:求\(n\)以内质数个数。通过枚举较小的那个质数的值,用min_25求解即可
#include<bits/stdc++.h> using namespace std; #define LL long long #define PB push_back vector<int>vis,prime,g; vector<vector<int> >f; LL n,ans; LL sqr(LL x){return x*x;} int getsqrt(LL n) { LL t=sqrt(n); while(sqr(t+1)<=n)t++; return t; } int getcbrt(LL n) { LL t=cbrt(n); while((t+1)*(t+1)*(t+1)<=n)t++; return t; } void sieve(int n) { vis.assign(n+1,0); prime.clear(); for(int i=2;i<=n;i++) { if(!vis[i]) { prime.PB(i); vis[i]=i; } for(int j=0;j<(int)(prime.size());j++) { if(prime[j]>vis[i] || prime[j]>n/i)break; vis[i*prime[j]]=prime[j]; } } } LL PI(LL n); LL F(LL n,int m) { if(!m)return n; if(prime[m]>n)return 0; if(m<(int)(f.size()) && n<(int)(f[m].size()))return f[m][n]; if(sqr(prime[m])>n)return PI(n)-m+1; return F(n,m-1)-F(n/prime[m-1],m-1); } LL PI(LL n) { if(n<=prime.back())return g[n]; int i=PI(getcbrt(n-1)+1); LL tmp=F(n,i)+i-1; while(true) { LL t=prime[i]; if(t*t>n)break; tmp-=PI(n/t)-i; i++; } return tmp; } void init(LL n) { sieve(getsqrt(n+1)*2); g.assign(prime.back()+1,0); int i,j; for(i=j=0;i<=prime.back();g[i++]=j)if(i==prime[j])j++; int A=131072,B=min((int)prime.size(),64); f.assign(B,vector<int>(A)); for(j=0;j<B;j++)for(i=0;i<A;i++)if(j==0)f[j][i]=i; else f[j][i]=f[j-1][i]-f[j-1][i/prime[j-1]]; } int main() { init(100000000000LL); scanf("%I64d",&n); for(LL i=0;sqr(prime[i])<n;i++) ans+=max(0ll,PI(n/prime[i])-i-1); return printf("%I64d\n",ans+PI(getcbrt(n))),0; }