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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

posted @ 2020-03-03 04:09  DeaphetS  阅读(134)  评论(0编辑  收藏  举报