Codeforces 1009

比赛链接

hack好给力啊233



A.Game Shopping

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1e3+5; int n,m,cost[N],A[N]; inline int read()
{
register int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
n=read(), m=read();
for(int i=1; i<=n; ++i) cost[i]=read();
for(int i=1; i<=m; ++i) A[i]=read();
int now=1,ans=0;
for(int i=1; i<=n && now<=m; ++i)
if(cost[i]<=A[now]) ++ans, ++now;
printf("%d\n",ans); return 0;
}

B.Minimum Ternary String

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=1e5+7; int n;
char s[N],ans[N]; int main()
{
scanf("%s",s+1), n=strlen(s+1);
int cnt[5],now;
cnt[0]=cnt[1]=cnt[2]=0;
for(now=1; now<=n; ++now)
if(s[now]!='2') ++cnt[s[now]-'0'];
else break;
for(int i=1; i<=cnt[0]; ++i) ans[i]='0';
for(int i=cnt[0]+1; i<=cnt[0]+cnt[1]; ++i) ans[i]='1';
cnt[0]=cnt[1]=cnt[2]=0;
for(int i=now; i<=n; ++i) ++cnt[s[i]-'0'];
for(int i=now; i<now+cnt[1]; ++i) ans[i]='1';
s[n+1]='3';
for(int i=now+cnt[1]; i<=n; ++i)
{
while(s[now]=='1') ++now;
ans[i]=s[now++];
}
puts(ans+1); return 0;
}/*
102012012
*/

C.Annoying Present

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define eps 1e-8
typedef long long LL;
const int N=1e5+7; inline int read()
{
register int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
} int main()
{
int n=read(), m=read();
LL sum=0, sumX=0, C1, C2=1ll*n*(n-1)>>1;//n/2写成n>>1略显乱
if(n&1) C1=1ll*(n>>1)*((n>>1)+1);
else C1=1ll*(n>>1)*((n>>1)+1)-1ll*(n>>1);
LL x,d;
for(int i=1; i<=m; ++i)
{
x=read(), d=read(), sumX+=x;
if(d>0) sum+=C2*d;
else if(d<0) sum+=C1*d;
}
printf("%.8lf",1.0*(sum+1ll*n*sumX)/n); return 0;
}

D.Relatively Prime Graph

靠 欺负我读英文题目不仔细吗 图必须连通。。

于是WA*3。看了数据才A。。

这破题 rank1000+了啊啊啊

而且这题n^2纯暴力都能过 太没意思了吧

#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define pr std::pair<int,int>
#define mp std::make_pair
const int N=1e5+7; int n,m,cnt,P[N],fac[N],sum;
pr A[3000005];
bool not_P[N]; int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
void Pre(int n)
{
for(int i=2; i<=n; ++i)
{
if(!not_P[i]) P[++cnt]=i;
for(int j=1; j<=cnt&&i*P[j]<=n; ++j)
{
not_P[i*P[j]]=1;
if(!(i%P[j])) break;
}
}
for(int i=2; i<=n; ++i)
if(!not_P[i]) fac[i]=i;
else{
for(int j=2; j<=i; ++j)
if(!(i%j)) {fac[i]=j; break;}
}
} int main()
{
scanf("%d%d",&n,&m);// printf("%d\n",m);
if(m<n-1) return puts("Impossible"),0;//...
Pre(n);
for(int i=2; i<=n && sum<m; ++i) A[++sum]=mp(1,i);
for(int x=1; x<=cnt && sum<m; ++x)
{
int i=P[x];
for(int j=i+1; j<=n && sum<m; )
{
int k=std::min(j+fac[i]-1,n+1);//n+1!
for(int l=j; l<k && sum<m; ++l) A[++sum]=mp(i,l);
j=k+1;
}
}
for(int i=4; i<=n && sum<m; ++i)
{
if(!not_P[i]) continue;
for(int j=i+1; j<=n && sum<m; )
{
int k=std::min(j+fac[i]-1,n+1);
for(int l=j; l<k && sum<m; ++l)
if(gcd(i,l)==1) A[++sum]=mp(i,l);
j=k+1;
}
}
if(sum<m) puts("Impossible");
else
{
puts("Possible");
for(int i=1; i<=m; ++i)
printf("%d %d\n",A[i].first,A[i].second);
} return 0;
}

比赛结束后

E.Intercity Travelling(递推)

\(Description\)

  Leha从0出发前往n。给定数组\(a[]\)。路上可能会有一些休息点,Leha会在这些地方停下休息。如果当前所在休息点\(i\),而上一个休息点是\(j\),那他会得到\(a_{i-j}\)的困难值(包括在n点停下也要计算,路程上所有累加)。休息点一共有\(2^{n-1}\)种可能分布,求所有可能中整段路程所得到的困难值的期望\(e\times 2^{n-1}\mod\ 998244353\)。

\(Solution\)

  要求一个线性做法,我们尝试递推求它。

  对每一个位置\(i\),我们可以写出它作为休息点时得到困难值的期望:\(e_i=\frac{a_1}{2}+\frac{a_2}{2^2}+\ldots+\frac{a_{i-1}}{2^{i-1}}+\frac{a_i}{2^{i-1}}\)。最后一项的概率是\(2^{i-1}\),因为是从0号点出发。

  那么就可以得到\(e_1=a_1,e_{i+1}=e_i-\frac{a_i}{2^i}+\frac{a_{i+1}}{2^i}\)。

//93ms	7700KB
#include <cstdio>
#include <cctype>
#define gc() getchar()
#define mod (998244353)
const int N=1e6+5; int n,A[N],pw[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
n=read();
for(int i=1; i<=n; ++i) A[i]=read();
pw[0]=1;
for(int i=1; i<=n; ++i) pw[i]=pw[i-1]<<1, pw[i]>=mod&&(pw[i]-=mod); long long now=1ll*A[1]*pw[n-1]%mod, ans=now;
for(int i=1; i<n; ++i)
{
now=(now-1ll*A[i]*pw[n-1-i]%mod+1ll*A[i+1]*pw[n-1-i]%mod+mod)%mod,
ans+=now;
}
printf("%I64d\n",ans%mod); return 0;
}

F.Dominant Indices(启发式合并)

显然对于\(d_{x,i}\),我们有\(d_{x,i}=\sum_{v=son[x]}d_{v,i-1}\)

Dominant Indices就是最大的\(d_{x,i}\)中下标最小的\(i\)。我们可以利用启发式合并求\(d_x\)。启发式合并一般的复杂度是\(O(n\log n)\)的,但在本题中,复杂度只与深度较小的点的深度有关,而不是点数。所以复杂度是\(O(n)\)的。

我们还需要将数组整体右移,以便插入一个\(d_{x,0}=1\)。可以用map(\(O(n\log n)\)),也可以用vector倒序存储,这样就是\(O(n)\)的了。

也可以直接用个大点的(\(O(n)\)其实就够了)数组,每个点维护在数组中的位置。

[Update]这就是dsu on tree或者长链剖分啊。

//546ms	89700KB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1e6+5; int n,Enum,H[N],nxt[N<<1],to[N<<1],Ans[N],A[N],pos[N],len[N],mx[N],mxpos[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void Merge(int x,int y)//x<-y
{
if(len[x]<len[y])
{
std::swap(pos[x],pos[y]), std::swap(len[x],len[y]),
std::swap(mx[x],mx[y]), std::swap(mxpos[x],mxpos[y]);
}
for(int i=0,ly=len[y],px=pos[x],py=pos[y]; i<ly; ++i)
{
A[px+i]+=A[py+i]; //A[px+i+1]+=A[py+i];
if(A[px+i]>mx[x]) mx[x]=A[px+i], mxpos[x]=i;
else if(A[px+i]==mx[x] && i<mxpos[x]) mxpos[x]=i;
}
}
void DFS(int x,int f)
{
A[pos[x]]=1, len[x]=1, mx[x]=1, mxpos[x]=0;
for(int v,i=H[x]; i; i=nxt[i])
if((v=to[i])!=f)
{
pos[v]=pos[x]+len[x]+1, DFS(v,x);//给v腾出一位,合并前将v右移一位。否则len[x]==len[v]时会重叠。。
A[--pos[v]]=0, ++len[v], ++mxpos[v], Merge(x,v);
}
Ans[x]=mxpos[x];
} int main()
{
n=read();
for(int i=1; i<n; ++i) AddEdge(read(),read());
pos[1]=1, DFS(1,1);
for(int i=1; i<=n; ++i) printf("%d\n",Ans[i]); return 0;
}

G.Allowed Letters(Hall定理 位运算)

\(Description\)

给定长为n、由小写字母a~f组成的字符串s。有m个限制,每个限制为:在\(pos_i\)处只能是某些字母(\(pos_i\)两两不同)。

你可以任意交换原串两个字母的位置,问是否能得到满足限制的串,若能,输出满足限制的最小字典序的字符串。

\(Solution\)

有n个字符,每个字符可以放在某些位置,要求这些字符全部放置->完备匹配。

可以跑网络流,检查最大流是否等于n,连边比较好想。然后假设想要让i位置放字符c,如果原最大流不需要c->i这条边,那么可以;否则让这条边退流,容量-1,再检查最大流是否等于n。

如果决定了位置i放字符c,那么要使c->i这条边的容量-1.

没写,万一调不出来有点。。Tutorial里说复杂度\(O(n*2^A*A^2)\)(A为字符集大小),不知道\(2^A\)是为什么。。(好像也是判子集合法?)

可以考虑Hall定理。对于任意一个字符的子集,其中字符个数要<=能够匹配其中字符的位置个数。

这样的话对于同一种字符,显然只需要检验包含它最多的子集(位置数不会变)。所以我们要检查的子集只有\(2^A=64\)个(A为字符集大小)。

任意子集包含字符的个数sum可以\(O(A*2^A)\)或\(O(2^A)\)算。对于(只要)能够匹配某子集s中任意字符 的位置数我们可以去算:位置总数-只能匹配除s中字符外的位置数。

除s中字符外的子集可以表示为2^A-1-s,预处理其包含的所有子集的位置数即可,记为f[]。

如果现在要确定i位置放什么,那要先减掉i对f的贡献,即枚举所有包括 位置i可放字符子集 的子集,依次-1。要放某字符首先要能放,然后数量-1,再Check就行了。

//62ms	400KB
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define lb(i) (i&-i)
const int N=1e5+7; int n,num[7],can[N],sum[69],f[69],bit[69];
char s[N],tmp[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
bool Check()
{
for(int i=1; i<64; ++i)
{
sum[i]=sum[i^lb(i)]+num[bit[lb(i)]];
if(sum[i]>f[63]/*not n,or n也-1*/-f[63-i]) return 0;
}
return 1;
} int main()
{
scanf("%s",s+1), n=strlen(s+1);
for(int i=1; i<=n; ++i) can[i]=63, ++num[s[i]-'a'];
for(int m=read(),p; m--; )
{
can[p=read()]=0, scanf("%s",tmp+1);
for(int j=1,l=strlen(tmp+1); j<=l; ++j)
can[p]|=1<<tmp[j]-'a';
}
for(int i=1; i<=n; ++i) ++f[can[i]];
for(int i=0; i<6; ++i)//求其包含的所有子集 先枚举i!
for(int j=1; j<64; ++j)
if(j>>i & 1)
f[j]+=f[j^(1<<i)];
for(int i=0; i<6; ++i) bit[1<<i]=i;
if(!Check()) return puts("Impossible"),0;
for(int i=1; i<=n; ++i)
{
for(int s=can[i]; s<=63; s=(s+1)|can[i]) --f[s];
for(int j=0; j<6; ++j)
{
if(!(can[i]>>j&1)) continue;
--num[j];
if(Check()) {putchar(j+'a'); break;}
++num[j];
}
}
return 0;
}

Educational Codeforces Round 47 (Div 2) (A~G)的更多相关文章

  1. Educational Codeforces Round 46 (Div 2) (A~G)

    目录 Codeforces 1000 A.Codehorses T-shirts B.Light It Up C.Covered Points Count(差分) D.Yet Another Prob ...

  2. Educational Codeforces Round 45 (Div 2) (A~G)

    目录 Codeforces 990 A.Commentary Boxes B.Micro-World C.Bracket Sequences Concatenation Problem D.Graph ...

  3. Educational Codeforces Round 84 (Div. 2)

    Educational Codeforces Round 84 (Div. 2) 读题读题读题+脑筋急转弯 = =. A. Sum of Odd Integers 奇奇为奇,奇偶为偶,所以n,k奇偶性 ...

  4. Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流

    题意:给你一个字符串,和每个位置可能的字符(没有就可以放任意字符)要求一个排列使得每个位置的字符在可能的字符中,求字典序最小的那个 题解:很容易判断有没有解,建6个点表示从a-f,和源点连边,容量为原 ...

  5. Educational Codeforces Round 47 (Rated for Div. 2) G. Allowed Letters

    把原字符看成 $X$,每个位置看成 $Y$,每种字符向每个能去的位置连边,就成了一个二分图完美匹配的问题.现要得到字典序最小,那么就枚举每一位要放什么,然后看放完这种字符,剩下的字符的个数和后面能不能 ...

  6. Educational Codeforces Round 47 (Rated for Div. 2) 题解

    题目链接:http://codeforces.com/contest/1009 A. Game Shopping 题目: 题意:有n件物品,你又m个钱包,每件物品的价格为ai,每个钱包里的前为bi.你 ...

  7. Educational Codeforces Round 47 (Rated for Div. 2) :E. Intercity Travelling

    题目链接:http://codeforces.com/contest/1009/problem/E 解题心得: 一个比较简单的组合数学,还需要找一些规律,自己把方向想得差不多了但是硬是找不到规律,还是 ...

  8. Educational Codeforces Round 47 (Rated for Div. 2) :D. Relatively Prime Graph

    题目链接:http://codeforces.com/contest/1009/problem/D 解题心得: 题意就是给你n个点编号1-n,要你建立m条无向边在两个互质的点之间,最后所有点形成一个连 ...

  9. Educational Codeforces Round 47 (Rated for Div. 2) :C. Annoying Present(等差求和)

    题目链接:http://codeforces.com/contest/1009/problem/C 解题心得: 题意就是一个初始全为0长度为n的数列,m此操作,每次给你两个数x.d,你需要在数列中选一 ...

随机推荐

  1. hadoop学习笔记之一步一步部署hadoop分布式集群

    一.准备工作 同一个局域网中的三台linux虚拟机,我用的是redhat6.4,如果主机是windows操作系统,可以先安装vmware workstation, 然后在workstation中装上3 ...

  2. LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树

    题目传送门:LOJ #3043. 题意简述: 你需要模拟线段树的懒标记过程. 初始时有一棵什么标记都没有的 \(n\) 阶线段树. 每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间 ...

  3. 【转】Shell编程进阶篇(完结)

    [转]Shell编程进阶篇(完结) 1.1 for循环语句 在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行. 它跟其他的循环,如while循环,最 ...

  4. oracle查看表名称和表字段注释

    --查询该表字段的注释select * from user_col_comments where Table_Name like '%SMS%' --查询类似表select * from user_t ...

  5. 【转】CString与string、char*的区别和转换

    我们在C++的开发中经常会碰到string.char*以及CString,这三种都表示字符串类型,有很多相似又不同的地方,常常让人混淆.下面详细介绍这三者的区别.联系和转换: 各自的区别 char*: ...

  6. odoo之model参数属性1

    1.基础文件及目录结构 在认识odoo ORM框架前,先介绍一下odoo中模块目录结构.   data:存放模块预制数据 i18n:存放国际化文件 models:存放模型等py代码 security: ...

  7. mysql通过centos本地命令行还原数据库出现乱码问题

    将sql文件上传到centos系统中,还原mysql数据库,发现是乱码 mysql -h10.11.8.62 -uroot -p dbtest </data/dbsql/dbtest.sql 数 ...

  8. HTML常用特殊字符

    网页特殊符号HTML代码大全   HTML特殊字符编码大全:往网页中输入特殊字符,需在html代码中加入以&开头的字母组合或以&#开头的数字.下面就是以字母或数字表示的特殊符号大全. ...

  9. C++ code:数值计算之矩形法求解积分问题

    积分的通常方法是将区域切割成一个个的小矩形,然后求这些小矩形的和.小矩形切割得越细,计算精度就越高,可以将切割小矩形的数量作为循环迭代变量,将前后两个不同精度下的小矩形和之差,作为逼近是否达到要求的比 ...

  10. 使用css3美化复选框

    声明:文章为转载(略改动),点击查看原文.如有侵权24小时内删除,联系QQ:1522025433. 我们知道HTML默认的复选框样式十分简陋,而以图片代替复选框的美化方式会给页面表单的处理带来麻烦,那 ...