发这篇博客的目的是因为刷了些水题,但又有一些不错的地方可以加以借鉴....然后又不想一个一个发....

Codeforces731A

题目大意:给出一个26个字母的环,初始指向a,可以顺时针转或者逆时针转,给出一个字符串求最少转几次能得到他。

题解:傻逼模拟。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char S[];
long long ans;
int main()
{
scanf("%s",S+); int len=strlen(S+);
int now,last,a; last='a';
for (int i=; i<=len; i++)
{
now=S[i];
if (now>last) a=now-last; else a=last-now;
ans+=min(a,-a);
last=now;
}
printf("%lld\n",ans);
return ;
}

731A

Codeforces731B

题目大意:给出一个序列,你可以进行两种操作,1.一个位置-2;2.相邻两个位置-1;问是否可以恰好使所有数减到0。

题解:贪心,因为最左边的相邻的只有它右边一个,所以可以从最左边的开始搞,注意不会减到0即可。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define N 200005
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int n,a[N],f[N];
int main()
{
n=read();
for(int i=;i<=n;i++) a[i]=read();
a[]%=;
for(int i=;i<=n;i++){
a[i]-=a[i-];
if(a[i] < ) { puts("NO"); return ; }
a[i]%=;
}
if(a[n]) puts("NO"); else puts("YES");
return ;
}

731B

Codeforces731C

题目大意:给出一个序列,每个位置有一个颜色,再给出一些区间要求这些区间中的颜色必须全都一样,求最少需要改变这个序列中的多少个位置,能使所有区间满足。

题解:可以用并查集搞一下,或者用连通分支搞一下。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int N,M,K,size,maxx,ans;
struct data{int l,r,f;}a[];
bool cmp(data x,data y) {return x.l==y.l? x.r<y.r : x.l<y.l;}
struct EdgeNode{int next,to;}edge[];
int head[],cnt=;
int st[],top;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
bool visit[];
int num[],c[];
void work(int x)
{
/*printf("%d\n",x);*/
visit[x]=; size++; num[c[x]]++; st[++top]=x;
if (num[c[x]]>maxx) maxx=num[c[x]];
for (int i=head[x]; i; i=edge[i].next) if (!visit[edge[i].to]) work(edge[i].to);
}
void clear()
{
for (int i=; i<=top; i++) num[c[st[i]]]--; top=;
}
int main()
{
N=read(),M=read(),K=read();
for (int i=; i<=N; i++) c[i]=read();
for (int i=; i<=M; i++) a[i].l=read(),a[i].r=read(),InsertEdge(a[i].l,a[i].r);
for (int i=; i<=N; i++)
if (!visit[i]) maxx=,size=,work(i),ans+=size-maxx,clear();/*,printf("a %d\n",i)*/
printf("%d\n",ans);
return ;
}

731C

Codeforces731D

题目大意:给出许多个序列,每次操作可以使这些数列中所有数+1,当一个数超过C后会还原成0,求最小需要几次操作后,满足给出的这些序列的按读入顺序且按字典序单调增,不行则输出-1。

题解:考虑每个序列和它前一个数列比较,如果能够比它前一个数列递增,能够得到一段满足的操作数的区间,然后对所有区间求交算答案即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int N,C,a[][],len[],x;
struct data{int l,r;}seg[]; int cnt;
inline bool cmp(data A,data B) {return A.l==B.l? A.r<B.r : A.l<B.l;}
int main()
{
N=read(),C=read();
x=;
for (int i=; i<=N; i++,x^=)
{
len[i]=read(); for (int j=; j<=len[i]; j++) a[x][j]=read();
if (i!=)
{
int le=min(len[i],len[i-]),pos=;
for (int j=; j<=le; j++)
if (a[x][j]==a[x^][j]) continue; else {pos=j; break;}
if (!pos && len[i]<len[i-]) {puts("-1"); return ;}
if (pos)
if (a[x][pos]>a[x^][pos])
seg[++cnt]=(data){C+-a[x][pos],C-a[x^][pos]};
else
seg[++cnt]=(data){,C-a[x^][pos]},seg[++cnt]=(data){C+-a[x][pos],C+};
}
}
for (int i=; i<=cnt; i++) if (seg[i].l>seg[i].r) swap(seg[i].l,seg[i].r);
// for (int i=1; i<=cnt; i++) printf("%d %d\n",seg[i].l,seg[i].r);
sort(seg+,seg+cnt+,cmp);
int pos=;
for (int i=; i<=cnt; i++)
if (pos<seg[i].l) break;
else pos=max(pos,seg[i].r+);
printf("%d\n",(pos<=C)? pos:-);
return ;
}

731D

Codeforces731E

题目大意:给出一个游戏,首先由一个数列,每次可以从左边开始选择一段数(>2个数)合并,并得到这段的分数,只剩一个数时结束,问双方都执行最优策略的时候,游戏结束时A最多比B多多少分。

题解:比较容易的dp,可以用前缀和优化,记录一下后缀最大值。dp的方程是$dp[i]=max(dp[i],sum[j]-dp[j])$,然而dp的值完全不用记录,可以直接扫一遍。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int N,a[],s[],ans;
int main()
{
scanf("%d",&N); for (int i=; i<=N; i++) scanf("%d",&a[i]),s[i]=s[i-]+a[i];
ans=s[N]; for (int i=N-; i>; i--) ans=max(ans,s[i]-ans); printf("%d\n",ans);
return ;
}

731E

Codeforces731F

题目大意:给一个序列,问从序列中找一个数,把不小于它的数变成它或者它的倍数,并使得这些数的和最大

题解:可以直接处理前缀和后暴力更新答案,之所以暴力的复杂度非常科学,因为这样是$\sum \frac{n}{i}$是调和级数,而它是发散的,所以复杂度并不大。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
int N,a[],n[],sn[],maxx;
LL ans,sum;
int main()
{
scanf("%d",&N);
for (int i=; i<=N; i++) scanf("%d",&a[i]),n[a[i]]++,maxx=max(maxx,a[i]);
for (int i=maxx; i; i--) sn[i]=sn[i+]+n[i];
for (int i=,j=i; i<=maxx; i++,j=i)
for (ans=max(ans,sum),sum=; n[i] && j<=maxx; j+=i)
sum+=(LL)j*(sn[j]-sn[j+i]);
ans=max(ans,sum);
printf("%I64d\n",ans);
return ;
}

731F

Codeforces148E

题目大意:有N行数,每次可以从某行的开头或结尾去掉一个数,并得到这个数的价值,问最多取M次的最大价值和是多少。

题解:背包DP,先一遍DP预处理出$f[i][j]$表示第i行取j个数的最大价值和,再利用$f[i][j]$进行DP求出$g[i][j]$表示前i行取j个数的最大价值和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define size(i) s[i].size()-1
vector<int>s[],sum[];
int f[][],g[][],N,M;
int main()
{
for (int i=; i<=; i++) s[i].push_back(),sum[i].push_back();
N=read(),M=read();
for (int x,i=,len,j; i<=N; i++)
for (len=read(),j=; j<=len; j++)
x=read(),s[i].push_back(x),sum[i].push_back(sum[i][j-]+s[i][j]);
for (int i=; i<=N; i++)
for (int j=; j<=size(i); j++)
for (int k=; k+size(i)-j-<=size(i); k++)
f[i][j]=max(f[i][j],sum[i][size(i)]-(sum[i][k+size(i)-j-]-sum[i][k-]));
// for (int i=1; i<=N; i++,puts(""))
// for (int j=1; j<=size(i); j++)
// printf("%d ",f[i][j]);
for (int i=,j,len=; i<=N; i++)
for (len+=size(i),j=; j<=len; j++)
for (int k=; k<=size(i); k++)
if (j>=k && len-(size(i))>=j-k)
g[i][j]=max(g[i][j],g[i-][j-k]+f[i][k]);
// for (int i=1; i<=N; i++,puts(""))
// for (int j=1; j<=size(i); j++)
// printf("%d ",g[i][j]);
printf("%d\n",g[N][M]);
return ;
}

148E

Codeforces285E

题目大意:求出满足good position的个数恰好为K个的全排列的个数  good position定义是$|a_{i}-i|=1$

题解:这类题显然可以DP+容斥。$dp[i][j][k][l]$表示前i个已经放了j个gp,k表示i是否被放过,l表示i+1是否被放过,这样就可以转移。 最后统计答案,注意$ans[j]$出现在$ans[i]$中的次数是$C[j][i]$次。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int N,K;
LL ans[],f[][][][],fac[],C[][];
#define P 1000000007
int main()
{
fac[]=; for (int i=; i<=; i++) fac[i]=fac[i-]*i%P;
N=read(),K=read();
C[][]=; for (int j,i=; i<=N; i++) for (C[i][]=,j=; j<=i; j++) C[i][j]=(C[i-][j]+C[i-][j-])%P;
f[][][][]=;
for (int i=; i<=N; i++)
for (int j=; j<=N-; j++)
for (int k=; k<=; k++)
for (int l=; l<=; l++)
(f[i][j+][l][]+=(!k)? f[i-][j][k][l]:)%=P,
(f[i][j+][l][]+=(i!=N)? f[i-][j][k][l]:)%=P,
(f[i][j][l][]+=f[i-][j][k][l])%=P;
for (int i=; i<=N; i++)
for (int j=; j<=; j++)
for (int k=; k<=; k++)
(ans[i]+=f[N][i][j][k])%=P;
for (int i=; i<=N; i++) (ans[i]*=fac[N-i])%=P;
for (int i=N; i>=; i--)
for (int j=i+; j<=N; j++) ans[i]=(ans[i]-ans[j]*C[j][i])%P,ans[i]+=(ans[i]<)? P:;
printf("%I64d\n",ans[K]);
return ;
}

285E

Codeforces148D

题目大意:一个袋子中一共有w个白球,b个黑球,公主和龙依次取一个球,取到率先白球的人获胜,每次龙取球,总会额外随机掉出一个球,求公主获胜的概率。

题解:显然概率DP,而且很好转移,$dp[i][j]$表示现在还剩i个白球,j个黑球的时公主先手的获胜概率,那么分情况讨论即可,转移可以看代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
double f[][];
int W,B;
int main()
{
for (int i=; i<=; i++) f[i][]=,f[][i]=;
for (int i=; i<=; i++)
for (int j=; j<=; j++)
f[i][j]+=(double)i/(i+j),
f[i][j]+=(j>=)? ((double)j/(i+j))*((double)(j-)/(i+j-))*((double)(j-)/(i+j-))*((double)f[i][j-]) : 0.0,
f[i][j]+=(j>= && i>=)? ((double)j/(i+j))*((double)(j-)/(i+j-))*((double)i/(i-+j-))*((double)f[i-][j-]) : 0.0;
while (scanf("%d%d",&W,&B)!=EOF) printf("%.9lf\n",f[W][B]);
return ;
}

148D

Codeforces268D

题目大意:一共有N层,每层有4个方向可以爬,一次最多爬高度H,从底部爬到至少N-H+1~N的高度的方案数。

题解:自己只会$O(NH^4)$的方法,就是$dp[i][n][e][s][w]$表示当前在第i层,北东南西四个方向分别距离为n/e/s/w的方案数,这样还需要滚动掉第i维。

正解也是如此,不过有很巧妙的优化,因为每一层的操作总会存在一个距离为0的转移,所以就可以压掉一维状态,这样复杂度就是$O(NH^{3})$,这种优化或者可以理解为把这些状态旋转的记录下来,可以类比旋梯。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
#define P 1000000009
int N,H;
LL f[][][][][],ans;
#define dpn(now,nor,eas,sou,wes) f[now&1][nor<H? 0:H][eas+(eas<H)][sou+(sou<H)][wes+(wes<H)]
#define dpe(now,nor,eas,sou,wes) f[now&1][nor+(nor<H)][eas<H? 0:H][sou+(sou<H)][wes+(wes<H)]
#define dps(now,nor,eas,sou,wes) f[now&1][nor+(nor<H)][eas+(eas<H)][sou<H? 0:H][wes+(wes<H)]
#define dpw(now,nor,eas,sou,wes) f[now&1][nor+(nor<H)][eas+(eas<H)][sou+(sou<H)][wes<H? 0:H]
int main()
{
scanf("%d%d",&N,&H);
f[][][][][]=;
for (int i=; i<=N; i++,memset(f[i&],,sizeof(f[i&])))
for (int nor=; nor<=H; nor++)
for (int eas=; eas<=H; eas++)
for (int sou=; sou<=H; sou++)
for (int wes=; wes<=H; wes++)
(dpn(i,nor,eas,sou,wes)+=f[(i-)&][nor][eas][sou][wes])%=P,
(dpe(i,nor,eas,sou,wes)+=f[(i-)&][nor][eas][sou][wes])%=P,
(dps(i,nor,eas,sou,wes)+=f[(i-)&][nor][eas][sou][wes])%=P,
(dpw(i,nor,eas,sou,wes)+=f[(i-)&][nor][eas][sou][wes])%=P;
for (int nor=; nor<=H; nor++)
for (int eas=; eas<=H; eas++)
for (int sou=; sou<=H; sou++)
for (int wes=; wes<=H; wes++)
(ans+=f[N&][nor][eas][sou][wes])%=P;
ans=(ans-f[N&][H][H][H][H]+P)%P;
printf("%I64d\n",ans);
return ;
}

268D未优化

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
#define P 1000000009
int N,H;
LL f[][][][][],ans;
int main()
{
scanf("%d%d",&N,&H);
f[][][][][]=;
for (int i=; i<=N; i++,memset(f[i&],,sizeof(f[i&])))
for (int a=; a<=; a++)
for (int b=; b<=H; b++)
for (int c=; c<=H; c++)
for (int d=; d<=H; d++)
(f[i&][!(a<)][b+(b<H)][c+(c<H)][d+(d<H)]+=f[(i-)&][a][b][c][d])%=P,
(f[i&][!(b<H)][c+(c<H)][d+(d<H)][a<? :H]+=f[(i-)&][a][b][c][d])%=P,
(f[i&][!(c<H)][d+(d<H)][a<? :H][b+(b<H)]+=f[(i-)&][a][b][c][d])%=P,
(f[i&][!(d<H)][a<? :H][b+(b<H)][c+(c<H)]+=f[(i-)&][a][b][c][d])%=P;
for (int a=; a<=; a++)
for (int b=; b<=H; b++)
for (int c=; c<=H; c++)
for (int d=; d<=H; d++)
(ans+=f[N&][a][b][c][d])%=P;
ans=(ans-f[N&][][H][H][H]+P)%P;
printf("%I64d\n",ans);
return ;
}

268D优化

Codeforces697D

题目大意:模拟求树的DFS序的过程,要求求出每个节点的DFS序的期望,以1号为根。

题解:树形DP,一个节点的DFS序编号为它前面的被遍历到的点的数目,所以可以考虑统计出每个节点的子树size,然后可以得到dp方程$f[v]=f[u]+1+\frac{size[u]-size[v]-1}{2}$,然后就可以得到了。这种题必须要手画数据才能得到!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 100010
int N;
struct EdgeNode{int next,to;}edge[MAXN<<];
int head[MAXN],cnt=,size[MAXN];
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
double f[MAXN];
void DFS_1(int now,int last)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
DFS_1(edge[i].to,now),size[now]+=size[edge[i].to];
}
void DFS_2(int now,int last)
{
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
f[edge[i].to]=f[now]++(double)(size[now]-size[edge[i].to]-)/,DFS_2(edge[i].to,now);
}
int main()
{
N=read();
for (int x,i=; i<=N; i++) x=read(),InsertEdge(x,i);
DFS_1(,); f[]=; DFS_2(,);
for (int i=; i<=N; i++) printf("%.1lf ",f[i]);
return ;
}

697D

Codeforces乱刷集合的更多相关文章

  1. Codeforces水题集合[14/未完待续]

    Codeforces Round #371 (Div. 2) A. Meeting of Old Friends |B. Filya and Homework A. Meeting of Old Fr ...

  2. 利用CH341A编程器刷新BIOS,恢复BIOS,妈妈再也不用担心BIOS刷坏了

    前几天,修电脑主析就捣鼓刷BIOS,结果刷完黑屏开不了机,立刻意识到完了,BIOS刷错了.就从网上查资料,各种方法试了个遍,什么用处都没有.终于功夫不负有心人,找到了编码器,知道了怎么用.下面看看具体 ...

  3. day09-2 字典,集合的内置方法

    目录 字典的内置方法 作用 定义方式 方法 优先掌握 需要掌握 存储一个值or多个值 有序or无序 可变or不可变 集合的内置方法 作用 定义方式 方法 存储一个值or多个值 有序or无序 可变or不 ...

  4. 蓝桥杯——Java集合练习题

    回文数.维密.约瑟夫环 回文数 问题描述: 123321是一个非常特殊的数,它从左边读和从右边读是一样的.输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n. 输入格式: ...

  5. NOI2018游记&我的OI历程

    day1 今天是报到日,坐着早上9点的飞机到了长沙,午饭时间到达雅礼洋湖. 宿舍还是一模一样,虽然是在女生宿舍. wifi信号还是一样的德行,刻意避开了宿舍内,只好把手机放在窗台上开热点. 饭菜还是如 ...

  6. Python 的经典入门书籍

    实python非常适合初学者入门,上手很容易.我就是完全通过网上资源学了python的.最大的是3点经验:1.找一本浅显易懂,例程比较好的教程,从头到尾看下去.不要看很多本,专注于一本.把里面的例程都 ...

  7. spring boot:使用validator做接口的参数、表单、类中多字段的参数验证(spring boot 2.3.1)

    一,为什么要做参数验证? 永远不要相信我们在后端接收到的数据, 1,防止别人通过接口乱刷服务:有些不怀好意的人或机构会乱刷我们的服务,例如:短信接口, 相信大家可能很多人在工作中遇到过这种情况 2,防 ...

  8. iOS 开源项目

    在 Github 上 Star 太多了,有时候很难找到自己想要的开源库,所以在此记录下来.便于自己开发使用,也顺便分享给大家. 动画 awesome-ios-animation收集了iOS平台下比较主 ...

  9. 红米3 TWRP-3.0.2(android_6.0.1_r72分支)中文版Recovery更新于20161018

    TWRP3.0.2更新简介 TWRP是TeamWin团队https://github.com/TeamWin/Team-Win-Recovery-Project的开源项目,也是Omnirom系统默认的 ...

随机推荐

  1. 【转】单例模式(singletion)

    单例模式(Singleton) 原地址:http://www.cnblogs.com/BoyXiao/archive/2010/05/07/1729376.html 首先来明确一个问题,那就是在某些情 ...

  2. netstat监控大量ESTABLISHED连接与Time_Wait连接问题

    问题描述: 在不考虑系统负载.CPU.内存等情况下,netstat监控大量ESTABLISHED连接与Time_Wait连接. # netstat -n | awk '/^tcp/ {++y[$NF] ...

  3. Git 工作流程

    Git 作为一个源码管理系统,不可避免涉及到多人协作. 协作必须有一个规范的工作流程,让大家有效地合作,使得项目井井有条地发展下去.”工作流程”在英语里,叫做”workflow”或者”flow”,原意 ...

  4. 全新的membership框架Asp.net Identity(1)——.Net membership的历史

    在Asp.net上,微软的membershop框架经历了Asp.net membership到Asp.net simple membership,再到现在的Asp.net Identity. 每一次改 ...

  5. AngularJs中,如何在render完成之后,执行Js脚本

    AngularJs是Google开源的前端JS框架.使用AngularJs, 我们能够容易地.健壮的开发出类似于Gmail一样的单页Web应用.AngularJs这个新兴的MVC前端框架,具有以下特点 ...

  6. SpringMVC @ModelAttribute注解

    /**     * 1. 有 @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用!      * 2. @ModelAttribute 注解也可以来修饰 ...

  7. window.frameElement的使用

    window.frameElement的使用: 返回嵌入当前window对象的元素(比如 <iframe> 或者 <object>),如果当前window对象已经是顶层窗口,则 ...

  8. ORA-00911: invalid character --- 字符集的问题

    网上搜了一遍, 大多数是因为分号( ; ) 的问题.  而我的sql文件是没有分号的, 最后发现是sql文件编码和服务器字符集的差异造成 sql文件怎么都看不出问题,直到在UltraEdit里切换到1 ...

  9. 骨骼蒙皮动画算法(Linear Blending Skinning)

    交互式变形是编辑几何模型的重要手段,目前出现了许多实时.直观的交互式变形方法.本文介绍一种利用线性混合蒙皮(Linear Blending Skinning,LBS)技术来实现网格变形的方法,线性混合 ...

  10. Oracle 增删改查

    Oracle入门案例: 1.创建实体类Student 并重写ToString方法 package cn.happy.entity; public class Student { public Inte ...