比赛感想##

本来21:05开始的比赛,结果记成21:30了。。。晚了25分钟才开始[捂脸]

这次是Educational Round,所以还比较简单。

前两道题一眼看去模拟+贪心,怕错仔细看了好几遍题,很快切掉

第三题,dfs+贪心

一开始想得有点简单,少了几种情况,写代码时才发现问题……

悲伤地发现 写+调 这道题用了我很长时间…(这叫什么?基础不牢,地动山摇!)

然后,居然只剩40分钟了……

第四题,啊啊啊!

图论,我的痛! 果断跳过

第五题,额,不就是个线段树么?

n<=10 \(^9\) ?不好不好,要动态开节点

噼里啪啦噼里啪啦……

提交。为什么超时了??? 我的常数真的这么大么??

调一调…还是不行。。(……比赛结束后才发现是编译器的问题……)

然后,居然只剩10分钟了……

第六题,啊啊啊!怎么又是图论!

图论,我的痛!果断跳过

第七题,数论,有关gcd

奇迹般地有了思路,可惜,时间不够没写完……

接着,悲伤地发现比赛结束了。悲伤地发现我只做对了3道水题…

嗯,水平还有很大提升空间啊,前方路还很长……


题目+题解##

Codeforces 915###

A. Garden###

Luba要给花园浇水,花园长度为k

她有n个水桶,每个水桶一次浇的长度为\(a_i\) (不能多也不能少)

她要选择1个水桶,使她浇得最快,且不会有地方被浇两次,不会浇到花园外面

求她浇完的最短时间。

(n,k,\(a_i\) \(\leq\) 100)

想法####

在ai中找到可整除k的最大的数,用k除以这个数便是答案

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; int main()
{
int n,k,i,x,ans=1000;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++){
scanf("%d",&x);
if(k%x!=0) continue;
ans=min(ans,k/x);
}
printf("%d\n",ans); return 0;
}

B. Browser###

Luba在浏览器中打开了n个标签,从左到右标号1~n

她只需[l,r]的标签,所以她要把其他的标签关上

她的鼠标停在第pos个标签页上

设她某时间鼠标位置为i,她可以有两种操作:

1.关闭[1,i-1]或[i+1,n]中所有开着的标签

2.将鼠标移到第i-1或第i+1个标签上 (前提:移到的那个标签必须是开着的)

求她把除[l,r]外其他标签都关闭的最少操作数。

(n \(\leq\) 100)

想法####

分情况考虑+贪心

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; int main()
{
int n,pos,l,r,s;
scanf("%d%d%d%d",&n,&pos,&l,&r); if(l==1 && r==n) printf("0\n");
else if(l==1) printf("%d\n",abs(r-pos)+1);
else if(r==n) printf("%d\n",abs(l-pos)+1);
else {
s=min(abs(l-pos),abs(r-pos));
s+=r-l+2;
printf("%d\n",s);
} return 0;
}

C. Permute Digits###

给定a与b,求 将组成a的数字重新排列,组成的不大于b的最大整数

注意,输出的整数与a的位数要一致,前导0要输出

(a,b \(\leq\) \(10^{18}\) )

想法####

若b的位数比a大,那么直接贪心,将组成a的数字从大到小输出

否则,先把在b前补0使它与a的位数一致,接着从高位往低位考虑贪心,dfs回溯判断是否可行,若贪心到某一位发现 a的这一位<b的这一位,后面的位直接贪心

代码####

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> using namespace std; int a[10];
char b[20],s[20];
int m,ans[20]; void Max(int cur){
for(int i=9;i>=0;i--)
for(int j=0;j<a[i];j++)
ans[cur++]=i;
}
bool dfs(int cur){
if(cur==m) return true;
int i;
if(a[i=b[cur]-'0']){
ans[cur]=i;
a[i]--;
if(dfs(cur+1)) return true;
a[i]++;
}
for(i=i-1;i>=0;i--)
if(a[i]){
ans[cur]=i;
a[i]--;
Max(cur+1);
return true;
}
return false;
} int main()
{
int i,n;
scanf("%s",s);
n=strlen(s);
for(i=0;i<n;i++) a[s[i]-'0']++;
scanf("%s",b);
m=strlen(b); if(m>n) Max(0);
else{
for(i=m-1;i>=0;i--) b[i+n-m]=b[i];
for(i=0;i<n-m;i++) b[i]='0';
m=n;
dfs(0);
}
for(i=0;i<n;i++) printf("%d",ans[i]);
printf("\n"); return 0;
}

D. Almost Acyclic Graph###

给定一个n个点m条边的有向图

问是否可以去掉一条边是图中不再有环

( 2 \(\leq\) n \(\leq\) 500 , 1 \(\leq\) m \(\leq\) min(n(n-1),100000) )

想法####

tarjan找scc,过程中记录某一个环

若scc数目n,则yes

否则,对于记录下来的那个环,试着把每条边删一遍,跑tarjan

若删掉某条边后的scc数目n,则yes

否则no (因为若删一条边满足条件的话,这条边一定在每个环中都出现)

代码####

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> using namespace std; const int N = 505; int dfn[N],map[N][N],low[N],vis[N],fa[N];
int scc,n,cnt;
int s[N],t;
int cir[N],tot; void dfs(int u){
dfn[u]=low[u]=++cnt;
s[t++]=u; vis[u]=1;
for(int v=1;v<=n;v++)
if(map[u][v]){
if(!dfn[v]){
fa[v]=u;
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],dfn[v]);
if(!tot){
for(int i=u;i!=v;i=fa[i]) cir[tot++]=i;
cir[tot++]=v;
}
}
}
if(dfn[u]==low[u]){
scc++;
while(s[t-1]!=u) vis[s[--t]]=0;
vis[s[--t]]=0;
}
}
void tarjan() { for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i); } int main()
{
int i,m,x,y,flag;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
scanf("%d%d",&x,&y),map[x][y]=1; tarjan();
if(scc==n) puts("YES");
else{
flag=0;
y=cir[tot-1];
for(i=0;i<tot;i++){
x=cir[i];
memset(dfn,0,sizeof(dfn));
map[x][y]=0;
cnt=scc=0; tarjan();
if(scc==n) { flag=1; break; }
map[x][y]=1;
y=cir[i];
}
if(flag) puts("YES");
else puts("NO");
} return 0;
}

E. Physical Education Lessons###

距学期结束还有n天,Alex需要在这n天上课

但由于他的学校上课时间常变动(共q次),所以他想知道每次变动后他需要上多少天课

有两种变动:

1.[l,r]都不上课

2.[l,r]都要上课

假设一开始他要上n天课

( 1 \(\leq\) n \(\leq\) \(10^9\) , 1 \(\leq\) q \(\leq\) 300000 )

想法####

标准的线段树啊

由于n最大1e9所以需要动态开节点

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; const int N = 300005; int n; struct node{
node *ch[2];
int sum,lazy;
}pool[N*50],*root;
int cnt; void pushdown(node *p,int l,int r){
int mid=(l+r)>>1;
if(!p->ch[0]){
p->ch[0]=&pool[++cnt];
p->ch[0]->sum=(mid-l+1);
p->ch[0]->lazy=-1;
}
if(!p->ch[1]){
p->ch[1]=&pool[++cnt];
p->ch[1]->sum=(r-mid);
p->ch[1]->lazy=-1;
}
if(p->lazy!=-1){
p->ch[0]->sum=(mid-l+1)*p->lazy;
p->ch[1]->sum=(r-mid)*p->lazy;
p->ch[0]->lazy=p->ch[1]->lazy=p->lazy;
p->lazy=-1;
} }
void update(node *p) { p->sum=p->ch[0]->sum+p->ch[1]->sum; }
void change(node *p,int l,int r,int L,int R,int k){
if(p->sum==(r-l+1)*k) return;
if(l==L && r==R){
p->sum=k*(r-l+1);
p->lazy=k;
return;
}
pushdown(p,l,r);
int mid=(l+r)>>1;
if(mid>=R) change(p->ch[0],l,mid,L,R,k);
else if(mid<L) change(p->ch[1],mid+1,r,L,R,k);
else{
change(p->ch[0],l,mid,L,mid,k);
change(p->ch[1],mid+1,r,mid+1,R,k);
}
update(p);
} int main()
{
int q,i,k,l,r;
scanf("%d%d",&n,&q); root=&pool[++cnt]; root->lazy=-1;
root->sum=n; for(i=0;i<q;i++){
scanf("%d%d%d",&l,&r,&k);
change(root,1,n,l,r,k-1);
printf("%d\n",root->sum);
} return 0;
}

F. Imbalance Value of a Tree###

给定一棵n个节点的树,每个点都有权值ai

函数I(x,y)的值为从x到y的唯一路径上点权最大-点权最小 (包括路径上的点x,y)

求所有点对的I(x,y)之和

(n \(\leq\) \(10^6\))

想法####

若是暴力枚举每对点的话,就算求I为O(1)也会超时

于是考虑函数I,实际上是求每对点间路径上的点权最小值之和 及 最大值之和

先考虑最小值

对于点权最小的那个点,显然所有经过它的路径上点权最小的都是它

对于点权次小的点,所有经过它且不经过点权最小点的路径上,点权最小的都为它

……

对于点权次大的点,它被计算当且仅当有一条边连接它与点权最大的点

对于点权最大的点,它不会被计算

由于是树,两两点间路径是唯一的

于是就有这样一种做法:将每条边按照所连两点权值较小值 从大到小排序

借助并查集,按排好的顺序合并边所连的两点,共n-1次

每次合并,两个集合中各任取一点,它们之间的路径上点权最小值为 这条边所连两点权值较小值

最大值同理,只不过是按边所连两点权值较大值 从小到大排序

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; const int N = 1000005;
typedef long long ll; struct edge{
int u,v;
}e[N]; int val[N],fa[N],size[N]; bool cmp1(edge x,edge y) { return min(val[x.u],val[x.v])>min(val[y.u],val[y.v]); }
bool cmp2(edge x,edge y) { return max(val[x.u],val[x.v])<max(val[y.u],val[y.v]); } int Getfa(int x) { return fa[x]==x ? x : fa[x]=Getfa(fa[x]); } int n; int main()
{
int i,x,y,v;
ll ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&val[i]);
for(i=1;i<n;i++) scanf("%d%d",&e[i].u,&e[i].v); for(i=1;i<=n;i++) fa[i]=i,size[i]=1;
sort(e+1,e+n,cmp1);
for(i=1;i<n;i++){
v=min(val[e[i].u],val[e[i].v]);
x=Getfa(e[i].u); y=Getfa(e[i].v);
if(size[x]<size[y]) swap(x,y);
ans-=(ll)v*size[x]*size[y];
fa[y]=x;
size[x]+=size[y];
} for(i=1;i<=n;i++) fa[i]=i,size[i]=1;
sort(e+1,e+n,cmp2);
for(i=1;i<n;i++){
v=max(val[e[i].u],val[e[i].v]);
x=Getfa(e[i].u); y=Getfa(e[i].v);
if(size[x]<size[y]) swap(x,y);
ans+=(ll)v*size[x]*size[y];
fa[y]=x;
size[x]+=size[y];
} printf("%lld\n",ans); return 0;
}

G. Coprime Arrays###

人们管满足 gcd(\(a_1\),\(a_2\),…,\(a_n\)) =1的数组a叫Coprime Array

给出n,k

设对于i \(\in\) [1,k] 满足每个元素都\(\in\)[1,i] 的Coprime Array的个数为\(b_i\)

求\(\sum\limits_{i=1}^k\) ( \(b_i\) ^ i)

(n,k \(\leq\) 2 \(\times\) \(10^6\))

想法一####

定义对于一个数组a,lgcd=gcd(\(a_1\),\(a_2\),…,\(a_n\))

设 每个元素都\(\in\)[1,i]的 满足lgcd=j 的数组个数为w[i][j]

那么b[i]=\(i^n\)-\(\sum\limits_{j=2}^i\) w[i][j]

很容易发现,w[i][j]=b[$ \frac {i} {j}$ ]

接下来跟“余数求和”有那么一点像

愉快地超时了……

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> #define P 1000000007 using namespace std; typedef long long ll;
const int N = 2000005; int PowerMod(int x,int b){
int ret=1;
while(b){
if(b&1) ret=((ll)ret*x)%P;
x=((ll)x*x)%P;
b>>=1;
}
return ret;
} int f[N];
int n,k; int main()
{
int i,l,r,ans;
scanf("%d%d",&n,&k); f[1]=1;
ans=0;
for(i=2;i<=k;i++){
f[i]=PowerMod(i,n);
for(l=2,r;l<=i;l=r+1){
r=i/(i/l);
if(r>i) r=i;
f[i]=(f[i]-((ll)r-l+1)*(f[i/l]-P))%P;
}
ans=(ans+(f[i]^i))%P;
}
printf("%d\n",ans); return 0;
}

想法二####

想一想可以发现,b数组是递增的

设f[i]=b[i]-b[i-1]

f[i]统计的是至少有一个元素为i的Coprime Array个数

和想法一的思路有一点点像

设 每个元素都\(\in\)[1,i]的 满足lgcd=j 且至少有一个元素为i 的数组个数为w[i][j]

由于确定数组中一定有一个数是i,那么算出的lgcd值只能为i的约数

很容易发现,w[i][j]=f[$\frac {i} {j} $ ]

那么f[i]=\(i^n\) - \((i-1)^n\) - \(\sum\){w[i][j] | j \(\in\) [1,i] , i mod j=0 } (无比神奇的sum用法。。。)

代码####

#include<cstdio>
#include<iostream>
#include<algorithm> #define P 1000000007 using namespace std; typedef long long ll;
const int N = 2000005; ll PowerMod(int x,int b){
ll ret=1;
while(b){
if(b&1) ret=(ret*x)%P;
x=((ll)x*x)%P;
b>>=1;
}
return ret;
} ll f[N],p[N];
int n,k; int main()
{
int i,j;
ll ans,sum;
scanf("%d%d",&n,&k); ans=sum=0;
for(i=1;i<=k;i++){
p[i]=PowerMod(i,n);
f[i]=(f[i]+p[i]-p[i-1]+P)%P;
sum=(sum+f[i])%P;
ans=(ans+(sum^i))%P;
for(j=i*2;j<=k;j+=i)
f[j]=(f[j]-f[i]+P)%P;
}
printf("%d\n",ans); return 0;
}

终于……

记第一场cf比赛(Codeforces915)的更多相关文章

  1. 记第一场atcoder和codeforces 2018-2019 ICPC, NEERC, Northern Eurasia Finals Online Mirror

    下午连着两场比赛,爽. 首先是codeforses,我和一位dalao一起打的,结果考炸了,幸亏不计rating.. A Alice the Fan 这个就是记忆化搜索一下预处理,然后直接回答询问好了 ...

  2. 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)

    比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子.   ...

  3. 暑假集训单切赛第一场 CF 191A Dynasty Puzzles

    题意不说了,看原题吧,思路见代码: #include <iostream> #include <stdio.h> #include <string.h> #incl ...

  4. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  5. 比赛总结——牛客网 NOIP赛前集训营提高组模拟第一场

    第一场打的很惨淡啊 t1二分+前缀最小值没想出来,20分的暴力也挂了,只有10分 t2数位dp,调了半天,结果因为忘了判0的特殊情况WA了一个点,亏死 t3emmmm.. 不会 imone说是DSU ...

  6. 校省选赛第一场C题解Practice

    比赛时间只有两个小时,我没有选做这题,因为当时看样例也看不懂,比较烦恼. 后来发现,该题对输入输出要求很低.远远没有昨天我在做的A题的麻烦,赛后认真看了一下就明白了,写了一下,一次就AC了,没问题,真 ...

  7. 校省选赛第一场A题Cinema题解

    今天是学校省选的第一场比赛,0战绩收工,死死啃着A题来做,偏偏一直WA在TES1. 赛后,才发现,原来要freopen("input.txt","r",stdi ...

  8. 2018牛客暑期ACM多校训练营第一场(有坑未填)

    (重新组队后的第一场组队赛 也是和自己队友的一次磨合吧 这场比赛真的算是一个下马威吧……队友上手一看 啊这不是莫队嘛 然后开敲 敲完提交发现t了 在改完了若干个坑点后还是依然t(真是一个悲伤的故事)然 ...

  9. 计蒜之道 初赛第一场B 阿里天池的新任务(简单)

    阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 ss 中出现了多少次. 首先,定义一个序列 ww: \displ ...

随机推荐

  1. Linux 内核 ksets 之上的操作

    对于初始化和设置, ksets 有一个接口非常类似于 kobjects. 下列函数存在: void kset_init(struct kset *kset); int kset_add(struct ...

  2. Xamarin 的一些资源汇总

    https://github.com/xamarin/xamarin-forms-sampleshttps://github.com/EgorBo/CrossChat-Xamarin.Formshtt ...

  3. codeforces 11D(状压dp)

    传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...

  4. js获取url参数值的方式

    定义方法: function getParam(paramName) { paramValue = ""; isFound = false; paramName = paramNa ...

  5. SQL SQL Index SEEK VS Lookup

    SEEK - find everything from index Lookup - find key from index, then visit table to find other row d ...

  6. 什么是特性(Attribute)?

    由面向对象思想,我们诞生了很多种面向对象编程语言,比如常用的Java,C#,这些语言中都共有类(Class)的概念,并用各自的方式去阐述.编写Class,或许方式不同,但它们都有一个共同点,即“类是对 ...

  7. $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基

    正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...

  8. JAVA8学习——从源码角度深入Stream流(学习过程)

    从源代码深入Stream / 学习的时候,官方文档是最重要的. 及其重要的内容我们不仅要知道stream用,要知道为什么这么用,还要知道底层是怎么去实现的. --个人注释:从此看出,虽然新的jdk版本 ...

  9. 2017 ACM-ICPC亚洲区域赛北京站J题 Pangu and Stones 题解 区间DP

    题目链接:http://www.hihocoder.com/problemset/problem/1636 题目描述 在中国古代神话中,盘古是时间第一个人并且开天辟地,它从混沌中醒来并把混沌分为天地. ...

  10. zabbix监控web应用日志报警并发送消息到钉钉

    首先在钉钉上开启钉钉机器人功能 说明:自定义关键词是zabbix发送过来的消息内容必须含有你定义的ERROR或者error字段,否则消息无法发送过来 ip地址段:一般都是zabbix-server的I ...