Educational Codeforces Round 74 (Rated for Div. 2)

  我叼,打的时候CF被ddos了,还有这种操做?害得我只能睡觉html

  最后一题留坑ios

   A. Prime Subtractionc++

   觉得是求GCD,上去wa一发。。。后来发现,y-x=C,若是C不为1,那么确定能够由素数组成,偶数直接+2,奇数就是3+2*k ,k>=0数组

#include<bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
using namespace std;
int main(){
  int t;
  LL a,b;
  scanf("%d",&t);
  while(t--){
    scanf("%lld%lld",&a,&b);
    if (a-b==1){
        printf("NO\n");
    }else {
        printf("YES\n");
    }
  }
  return 0;
}
View Code

  B 先打远的,每次打完,判断一下是否有被震到x<0的,直接模拟便可ide

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int maxx = 2e5+6;
int a[maxx];
vector<int>v;
bool cmp(int x,int y){
   return x<y;
}
int main(){
   int q;
   int n;
   long long rr;
   scanf("%d",&q);
   while(q--){
      v.clear();
      scanf("%d%lld",&n,&rr);
      for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        v.push_back(a[i]);
      }
      sort(v.begin(),v.end(),cmp);
      v.erase(unique(v.begin(),v.end()),v.end());
      int l=0,r=v.size()-1;
      long long step=0;
      int ans=0;
      while(l<=r){
         ans++;
         r--;
         step+=rr;
         while(l<=r && v[l]-step<=0){
             l++;
         }
      }
      printf("%d\n",ans);
   }
   return 0;
}
View Code

  C. Standard Free2playui

   咱们发现只要两个数间隔差>=2好比5-3,你必定能够先到4;100-1你必定能够先到2,而后咱们判断若是当前和下一个是连续的,也就是说3-2,那么你能够先到4,而后3的状态改变,而后到2,不然就不行,咱们spa

就必须用一个魔法值,前面说了a[i+1]-a[i]>1那么你能够直接改变当前i的状态,而后走到a[i+1]+1的状态。最后判断一下,最后的状态是否是高度大于2,若是是的话,咱们直接改变最后的状态,而后就能够到0了。3d

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int maxx = 2e5+6;
int a[maxx];
int main(){
  int t;
  int h,n;
  scanf("%d",&t);
  while(t--){
    scanf("%d%d",&h,&n);
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int cnt=0;
    for (int i=1;i<=n;i++){
        if (a[i]>=h){
            continue;
        }
        if (h-a[i]>1){
            h=a[i]+1;
        }
        if (i<n){
            if (a[i+1]==a[i]-1){
                h=a[i+1];
            }else{
                cnt++;
                h=a[i];
            }
            continue;
        }
        if (h>2)cnt++;
    }
    printf("%d\n",cnt);
  }
  return 0;
}
View Code

  D  找出全部的串,每个字符都至少属于一个回文串,发现其实这种回文串不少,咱们反着考虑,找不知足的,那么只有ABBBBB,BAAAAAA,AAAAB,BBBBBA这四种类型,其余的都是,由于字符毕竟只有两种,code

那么先后扫一遍便可,htm

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#define LL long long
using namespace std;
const int maxx= 3e5+6;
char a[maxx];
int main(){
  LL n;
  while(~scanf("%lld",&n)){
    scanf("%s",&a);
    int len=strlen(a);
    LL ans=n*(n-1)/2;
    int pre=0;
    for (int i=1;i<len;i++){
        if (a[i]==a[i-1])continue;
        ans++;
        ans-=(i-pre);
        pre=i;
    }
    pre=len-1;
    for (int i=len-2;i>=0;i--){
        if (a[i]==a[i+1])continue;
        ans-=(pre-i);
        pre=i;
    }
    printf("%lld\n",ans);
  }
  return 0;
}
View Code

  E 颇有意思,咱们暂时也不怎么懂,这个DP太秀了。。。咱们发现位数只有20位,那么其实能够经过枚举已经安排的状态来考虑。

  当前状态i表明当前i的二进制位上的英文单词是否被安排

  参考一下

http://www.javashuo.com/article/p-tynacpbm-dk.html

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxx = 1e5+6;
const int maxn = 2e6+7;
char str[maxx];
LL dp[maxn];
LL cnt[30][30];
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        scanf("%s",str);
        int len=strlen(str);
        for (int i=1;i<len;i++){
             int x=str[i-1]-'a';
             int y=str[i]-'a';
             if (x!=y)cnt[x][y]++,cnt[y][x]++;
        }
        for (int i=1;i<=(1<<m);i++){
            dp[i]=INT_MAX;
        }
        for (int i=0;i<(1<<m)-1;i++){
            LL c=__builtin_popcount(i);
            for (int j=0;j<m;j++){
                if(!(i&(1<<j))){
                    LL tmp=dp[i];
                    for (int k=0;k<m;k++){
                        if (i&(1<<k)){
                            tmp+=cnt[j][k]*c;
                        }else {
                            tmp-=cnt[j][k]*c;
                        }
                    }
                    dp[i|(1<<j)]=min(dp[i|(1<<j)],tmp);
                }
            }
        }
        printf("%lld\n",dp[(1<<m)-1]);
    }
    return 0;
}
View Code

 F  树上毛毛虫

 其实就是找一条链,与这个链直接相连的节点尽量的多。

 其实树形DP,就能够,咱们维护两个大的DP值,表明儿子节点中最大的两个值,dp[i],表明i的子树中链上所链接的点尽量的多。

那么对于每一个节点,维护一个maxx,minn,表明不一样的儿子节点中,子树链上链接的点,最多的和次多的,而后维护一个maxx+minn+son[i]-2+1表示把两个链连在一块儿,加上当前节点的儿子节点的个数,减去因为maxx和minn链上两个点是在son里面,再加上当前节点自己。

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#define LL long long
using namespace std;
const int maxx = 3e5+6;
int ver[maxx*2],Next[maxx*2],head[maxx];
int n,m,tot;
int dp[maxx],son[maxx];
int ans;
void add(int x,int y){
  ver[++tot]=y;Next[tot]=head[x];head[x]=tot;
  ver[++tot]=x;Next[tot]=head[y];head[y]=tot;
  son[x]++;
  son[y]++;
}
void dfs(int u,int fa){
   dp[u]=1;
   int minn=0,maxx=1;
   for (int i=head[u];i;i=Next[i]){
      int v=ver[i];
      if (v==fa)continue;
      dfs(v,u);
      if (maxx<dp[v]){
          minn=maxx;
          maxx=dp[v];
      }else if (minn<dp[v]){
          minn=dp[v];
      }
      dp[u]=max(dp[u],dp[v]+son[u]-1);
   }
   ans=max(minn+maxx+son[u]-1,ans);
}
int main(){
  int uu,vv;
  int t;
  scanf("%d",&t);
  while(t--){
    scanf("%d",&n);
     ans=0;
     for (int i=1;i<=n;i++){
        dp[i]=0;
        head[i]=0;
        son[i]=0;
     }
     for (int i=1;i<=n-1;i++){
        scanf("%d%d",&uu,&vv);
        add(uu,vv);
     }
     dfs(1,0);
     printf("%d\n",ans);
  }
  return 0;
}
View Code
相关文章
相关标签/搜索