Codeforces乱刷集合
发这篇博客的目的是因为刷了些水题,但又有一些不错的地方可以加以借鉴....然后又不想一个一个发....
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乱刷集合的更多相关文章
- Codeforces水题集合[14/未完待续]
Codeforces Round #371 (Div. 2) A. Meeting of Old Friends |B. Filya and Homework A. Meeting of Old Fr ...
- 利用CH341A编程器刷新BIOS,恢复BIOS,妈妈再也不用担心BIOS刷坏了
前几天,修电脑主析就捣鼓刷BIOS,结果刷完黑屏开不了机,立刻意识到完了,BIOS刷错了.就从网上查资料,各种方法试了个遍,什么用处都没有.终于功夫不负有心人,找到了编码器,知道了怎么用.下面看看具体 ...
- day09-2 字典,集合的内置方法
目录 字典的内置方法 作用 定义方式 方法 优先掌握 需要掌握 存储一个值or多个值 有序or无序 可变or不可变 集合的内置方法 作用 定义方式 方法 存储一个值or多个值 有序or无序 可变or不 ...
- 蓝桥杯——Java集合练习题
回文数.维密.约瑟夫环 回文数 问题描述: 123321是一个非常特殊的数,它从左边读和从右边读是一样的.输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n. 输入格式: ...
- NOI2018游记&我的OI历程
day1 今天是报到日,坐着早上9点的飞机到了长沙,午饭时间到达雅礼洋湖. 宿舍还是一模一样,虽然是在女生宿舍. wifi信号还是一样的德行,刻意避开了宿舍内,只好把手机放在窗台上开热点. 饭菜还是如 ...
- Python 的经典入门书籍
实python非常适合初学者入门,上手很容易.我就是完全通过网上资源学了python的.最大的是3点经验:1.找一本浅显易懂,例程比较好的教程,从头到尾看下去.不要看很多本,专注于一本.把里面的例程都 ...
- spring boot:使用validator做接口的参数、表单、类中多字段的参数验证(spring boot 2.3.1)
一,为什么要做参数验证? 永远不要相信我们在后端接收到的数据, 1,防止别人通过接口乱刷服务:有些不怀好意的人或机构会乱刷我们的服务,例如:短信接口, 相信大家可能很多人在工作中遇到过这种情况 2,防 ...
- iOS 开源项目
在 Github 上 Star 太多了,有时候很难找到自己想要的开源库,所以在此记录下来.便于自己开发使用,也顺便分享给大家. 动画 awesome-ios-animation收集了iOS平台下比较主 ...
- 红米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系统默认的 ...
随机推荐
- 又一个高性能轻量级的iOS模型框架YYModel
前言 iOS的模型框架其实有很多了,去年研究过Mantle,也了解过JSONModel.MJExtension,最近的项目项目优化的时候,再次考虑,基于轻量级.高性能的考虑,最终选择了YYModel. ...
- python之选课系统详解[功能未完善]
作业需求 思路:1.先写出大体的类,比如学校类,学生类,课程类-- 2.写出类里面大概的方法,比如学校类里面有创建讲师.创建班级-- 3.根据下面写出大致的代码,并实现其功能 遇到的困 ...
- VSALM 动手实验 - 持续集成
Visual Studio 应用生命周期管理(VSALM - Visual Studio Application Lifecycle Managemnet)是微软基于Visual Studio产品线所 ...
- Attempt to fetch logical page (...) in database 2 failed. It belongs to allocation unit xxxx not to xxx
今天一个同事说在一个生产库执行某个存储过程,遇到了错误: Fatal error 605 occurred at jul 29 2014 我试着执行该存储过程,结果出现下面错误,每次执行该存储过程,得 ...
- javascript-桥接模式
桥接模式 1.在系统沿着多个维度变化的同时,又不增加其复杂度并以达到解耦 2.最主要特点:将实现层(如元素绑定的事件)与抽象层(如修饰页面UI逻辑)解耦分离,使两部分独立变化 3.避免需求的改变造成对 ...
- HTML入门篇
HTML HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏 ...
- 交互式makefile
之前一直不知道在shell中调用read赋值后,怎么传给makefile中的变量,后来才恍然大悟. myname := $(shell read -p "Enter your name:&q ...
- Log4J基础详解及示例大全
去年这个时候,为做软件工程的大作业就详细学过Log4J的用法了,时隔一年想要在新的项目中好好使用一下的时候,发现几乎全忘了,悲催啊-- 再上网查资料,总是不能找到一篇符合我的口味,拿来就能轻松上手,方 ...
- android 项目中出现红色感叹号的解决方法
问题原因]:工程中classpath中指向的包路径错误 [解决办法]:右键项目名称 BuildPath ---> Configure Build Paht...中,然后上面有几个选项卡找到 Li ...
- Windows 设置Mongodb
安装MongoDB 将解压所得的bin文件夹内文件部署于C:\mongodb\bin 建立数据库文件夹 C:\mongodb\data\db 准备以下内容的配置文件mongodb.cfg dbpath ...