我叼,打的时候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; }
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; }
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; }
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; }
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; }
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; }