Codeforces Round #564(div2)

本来以为是送分场,结果成了送命场.

菜是原罪

A

SB题,上来读不懂题就交WA了一发,代码就不粘了

B

简单构造

很明显,\(n*n\)的矩阵可以按照这个顺序排列

然后根据\(n\)的大小搞一搞就好了

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
using namespace std;
const int N = 1e5 + 3;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int n,m;
int aa[N];
int main(){
n = read();
aa[1] = 1;
for(int i = 1;i <= 10000;++i) aa[i] = 2 * i - 1;
int now = 1;
while(aa[now] < n) now++;
printf("%d\n",now);
for(int i = 1;i <= now;++i)
printf("1 %d\n",i);
int cc = 2;
for(int i = now + 1;i <= n;++i)
printf("%d %d\n",cc,now),cc++;
return 0;
}

C

送命题,卡了一个多小时,非常思维的一道题目

首先,答案肯定不会超过\(2*n\),最坏情况我们将非空白牌都攒在手上然后一张一张打出

我们有两种策略

1:直接将手中的牌打出,这时需要满足队尾的一个\(1\)开头的连续字段的结尾的下一张牌在我们的手中,后者我们可以通过上一次摸到.所以如果队尾有连续子段,那么我们就判一下能否直接插入,若果可以,显然这是最优解

2:当队尾不符合上述条件,或者我们没办法接上连续字段时,我们就要一直攒牌,在某一时刻依次打出

我们设\(p_i\)表示\(i\)号牌在队列中的位置(不在队列视为\(0\)),接着,若果我们在\(p_i\)成为队头的时刻(设为\(t\))打出

首先需要满足\(\max_{i = t}^npi - (i - 1) == p_i-(i - 1)\)

\(p_i-(i - 1)\)是最难理解的地方.

我理解为我们插入了\(i - 1\)次时,还有要几步才可以将\(i\)给搞出来(此时我们已经默认我们有了\(1—i - 1\))

也就是说,我确保手里有\(1—i - 1\)并且至少再插完\(i - 1\)之前摸到\(i\)必须再插入\(p_i-(i - 1)\)次,因为我的手中有\(1—i- 1\),这个是不算贡献的(或者重叠部分只算一次)

但是如果这时我们手中没有\(i - 1\)该怎么办?

没关系,如果出现上述情况\(p_{i - 1}\)一定在\(p_i\)后面,我们取得是最大值,\(p_{i + 1}\)的贡献显然要大

所以答案就是\(n + max_{i =1}^np_i-i+1\)

#include<cstdio>
#include<cctype>
#include<iostream>
using namespace std;
const int N = 2e5 + 3;
int p[N];
int a[N];
int b[N];
int book[N];
int n;
inline bool check(){
for(int i = 1;i <= n;++i) if(book[i] == 0) return false;
return true;
}
int main(){
scanf("%d",&n);
for(int i = 1;i <= n;++i) scanf("%d",&a[i]),book[a[i]] = 1;
for(int i = 1;i <= n;++i) scanf("%d",&b[i]),p[b[i]] = i;
// bool flag = 0;
int now = n;
while(now >= 2 && b[now - 1] != 0 && b[now - 1] == b[now] - 1) now--;
// cout << now << endl;
int t = 1;
if(b[now] == 1){
for(int i = 1;i <= b[n];++i) book[i] = 1;
for(int i = b[n] + 1;i <= n;++i){
if(!book[i]){break;}
book[b[t]] = 1;
t++;
// cout << t << endl;
}
if(check()){
printf("%d\n",now - 1);
return 0;
}
}
// cout << flag << endl;
// cout << t << endl;
// cout << "GG";
int ans = 0;
for(int i = 1;i <= n;++i)
ans = max(ans,p[i] - i + 1);
printf("%d\n",ans + n);
return 0;
}

D

首先,我们发现每一颗子树一定是连续的一段圆弧,所以每一颗子树互不影响,那么我们考虑\(DP\)求贡献

我们固定跟,设\(f_i\)表示以\(i\)为跟时的答案

\(f_i = (son_i + [i !=root])!\prod_{j\in son_i}f_j\)

\(ans = nf_{root}\)

为什么呢

想一下,由于每颗子树是互不影响的所以总答案一定和子树答案的乘积有关,又因为他们的相对顺序没有限制

所以和儿子数量的阶乘有关系,但是当前父节点不为跟时,也要参与排列.

而跟有\(n\)个位置可以放

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
using namespace std;
const int N = 3e5 + 3;
const LL mod = 998244353;
vector <int> G[N];
LL ans = 0;
int son[N];
LL dp[N];
LL inv[N];
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int n;
inline void dfs(int x,int f){
dp[x] = 1;
for(int i = 0;i < (int)G[x].size();++i){
int y = G[x][i];
if(y == f) continue;
dfs(y,x);
son[x]++;
}
int w = (x != 1) ? son[x] + 1: son[x];
for(int i = 0;i < (int)G[x].size();++i){
int y = G[x][i];
if(y == f) continue;
dp[x] = dp[x] * dp[y] % mod;
}
dp[x] = dp[x] * inv[w] % mod;
}
int main(){
inv[0] = 1; n = read();for(int i = 1;i <= n;++i) inv[i] = inv[i - 1] * i % mod;
for(int i = 1;i < n;++i){
int x = read(),y = read();
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0);
printf("%I64d\n",dp[1] * n % mod);
return 0;
}

E

题目大意:给你\(n\)件物品,每件物品有其价值,以及是否喜欢,每次有\(\frac{w_i}{\sum{w_i}}\)的几率选择\(i\)

如果\(i\)是他喜欢的,就把他的价值\(+1\),否则如果是他不喜欢的就把他\(-1\),但价值最小为\(0\).

求操作\(m\)次后每个物品的价值的期望

这道题,我们可以把喜欢的和不喜欢的综合起来看成两个物品

感性理解一下,就是喜欢的物品之间的价值比无论选择多少次期望是不变的.

同理不喜欢的物品之间期望的相对的价值比也是不会变的.

我们设\(f_{i,j}\)表示选择了\(i\)次,有\(j\)次选择了喜欢的概率.

我们设\(sum_1\)表示喜欢的物品的价值之和

\(sum_2\)表示不喜欢的物品的价值之和

很明显

\(f_{i + 1,j + 1} = f_{i,j} * (sum_1 + j ) / (sum_1+sum_2+j - (i - j))\)

\(f_{i + 1,j} = f_{i,j}*(sum_2-(i - j))/(sum1 + sum2 + j - (i - j))\)

之后我们设\(r_1\)表示操作完之后喜欢的物品的期望价值之和

设\(r_2\)表示不喜欢的物品的期望价值之和

则有

\(r_1 = \sum_{i = 0}^m{f_{m,i}*(sum_1+i)}\)

\(r_2=\sum_{i = 0}^mf_{m,i}*(sum_2-(m - i))\)

最终根据本来占比直接乘回去就好了

#include<cstdio>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define LL long long
using namespace std;
const LL mod = 998244353;
const int N = 5e3 + 3;
const int M = 5e5 + 3;
LL f[N][N];
int n,m;
LL ans[M];
int a[M],w[M];
LL sum1,sum2;
inline LL quick(LL x,LL y){
if(x < 0) return 0;
LL res = 1;
while(y){
if(y & 1) res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
for(int i = 1;i <= n;++i){
scanf("%d",&w[i]);
if(a[i] == 1) sum1 += w[i];
else sum2 += w[i];
}
f[1][1] = sum1 * quick(sum1 + sum2,mod - 2) % mod;
f[1][0] = sum2 * quick(sum1 + sum2,mod - 2) % mod;
for(int i = 1;i < m;++i){
for(int j = 0;j <= i;++j){
int g = i - j;
f[i + 1][j + 1] = (f[i + 1][j + 1] + f[i][j] * (sum1 + j) % mod * quick(sum1 + sum2 + j - g,mod - 2)) % mod;
f[i + 1][j] = (f[i + 1][j] + f[i][j] * max(0ll,sum2 - g) % mod * quick(sum1 + sum2 + j - g,mod - 2)) % mod;
}
}
//for(int i = 1;i <)
//for(int i = 0;i <= m;++i){
LL r1 = 0,r2 = 0;
for(int i = 0;i <= m;++i){
r1 = (r1 + f[m][i] * (sum1 + i)) % mod;
r2 = (r2 + f[m][i] * (max(0ll,sum2 - m + i))) % mod;
}
for(int i = 1;i <= n;++i){
if(a[i] == 1) ans[i] = r1 * w[i] % mod * quick(sum1,mod - 2) % mod;
else ans[i] = r2 * w[i] % mod * quick(sum2,mod - 2) % mod;
printf("%I64d\n",ans[i]);
}
//}
return 0;
}

Codeforces Round #564(div2)的更多相关文章

  1. Codeforces Round #539 div2

    Codeforces Round #539 div2 abstract I 离散化三连 sort(pos.begin(), pos.end()); pos.erase(unique(pos.begin ...

  2. 【前行】◇第3站◇ Codeforces Round #512 Div2

    [第3站]Codeforces Round #512 Div2 第三题莫名卡半天……一堆细节没处理,改一个发现还有一个……然后就炸了,罚了一啪啦时间 Rating又掉了……但是没什么,比上一次好多了: ...

  3. Codeforces Round#320 Div2 解题报告

    Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Fin ...

  4. Codeforces Round #564 (Div. 1)

    Codeforces Round #564 (Div. 1) A Nauuo and Cards 首先如果牌库中最后的牌是\(1,2,\cdots, k\),那么就模拟一下能不能每次打出第\(k+i\ ...

  5. Codeforces Round #361 div2

    ProblemA(Codeforces Round 689A): 题意: 给一个手势, 问这个手势是否是唯一. 思路: 暴力, 模拟将这个手势上下左右移动一次看是否还在键盘上即可. 代码: #incl ...

  6. Codeforces Round #626 Div2 D,E

    比赛链接: Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics) D.Present 题意: 给定大 ...

  7. CodeForces Round 192 Div2

    This is the first time I took part in Codeforces Competition.The only felt is that my IQ was contemp ...

  8. Codeforces Round #359 div2

    Problem_A(CodeForces 686A): 题意: \[ 有n个输入, +\space d_i代表冰淇淋数目增加d_i个, -\space d_i表示某个孩纸需要d_i个, 如果你现在手里 ...

  9. Codeforces Round #360 div2

    Problem_A(CodeForces 688A): 题意: 有d天, n个人.如果这n个人同时出现, 那么你就赢不了他们所有的人, 除此之外, 你可以赢他们所有到场的人. 到场人数为0也算赢. 现 ...

随机推荐

  1. 新一代互联网传输协议QUIC浅析

    QUIC(Quick UDP Internet Connection)是谷歌制定的一种互联网传输层协议,它基于UDP传输层协议,同时兼具TCP.TLS.HTTP/2等协议的可靠性与安全性,可以有效减少 ...

  2. awss3

    import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io ...

  3. python 模块的作用

  4. Spark in action on Kubernetes - Spark Operator的原理解析

    前言 在上篇文章中,向大家介绍了如何使用Spark Operator在kubernetes集群上面提交一个计算作业.今天我们会继续使用上篇文章中搭建的Playground进行调试与解析,帮助大家更深入 ...

  5. 【Mysql的那些事】数据库之ORM操作

    1:ORM的基础操作(必会) <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> get(* ...

  6. JDK 8 中包列表及介绍

    了解了Java 8中所有包的作用,对Java 8有了一个整体的了解,另外也是提高了自身的阅读能力.本文列出了Java 8中所有的包,并且对每一个包的功能做了简要的说明,希望对你有所帮助. ------ ...

  7. 2019-8-31-C#-通过-probing-指定-dll-寻找文件夹

    title author date CreateTime categories C# 通过 probing 指定 dll 寻找文件夹 lindexi 2019-08-31 16:55:58 +0800 ...

  8. C# —— 枚举

    一.使用枚举的优点 枚举能够使代码更加的清晰,它允许使用描述性的名称表示整数值. 枚举使代码更易于维护,有助于确保给变量指定合法的.期望的值. 枚举使代码更易输入. 二.枚举说明 1.简单枚举 枚举使 ...

  9. Oracle包utl_inaddr

    作用:用于取得局域网或Internet环境中的主机名和IP地址. 1.utl_inaddr.get_host_address 环境中IP地址 如果查询失败,则提示系统错误 查询www.qq.com的I ...

  10. Python深入:01内存管理

            在Python中,一切都是指针. 一:对象三特性         所有的Python对象都有三个特性:身份,类型和值.         身份:每一个对象都有一个唯一的身份标识,任何对象 ...