CodeForces1151

Maxim and Biology

解析:

题目大意

每次可以使原串中的一个字符\(+1/-1\),\(Z + 1\to A, A -1\to Z\),求至少修改多少次可以使 ACTG 是原串的子串

\(4\le |S|\le 50\)


思路:

直接暴力尝试每个子串。


code

#include <bits/stdc++.h>
const int N = 50 + 10;
const int INF = 0x3f3f3f3f;
using namespace std;
int n, ans;
char s[N];
signed main()
{
scanf ("%d%s", &n, s + 1); ans = INF;
for (int i = 1; i <= n - 3; i++)
{
ans = min (ans, min (abs(s[i] - 'A'), 26 - abs((s[i] - 'A'))) +
min (abs(s[i + 1] - 'C'), 26 - abs((s[i + 1] - 'C'))) +
min (abs(s[i + 2] - 'T'), 26 - abs((s[i + 2] - 'T'))) +
min (abs(s[i + 3] - 'G'), 26 - abs((s[i + 3] - 'G'))));
}
printf ("%d\n", ans);
return 0;
}

Dima and a Bad XOR

解析:

题目大意:

给你一个大小为 \(n \times m\) 的矩阵,其中只包含非负整数。你需要从矩阵的每一行中选出一个整数,使得所选整数的按位异或严格大于零。

输出 \(n\) 行,每行一个正整数表示选择选当前第几个数。


思路:

考虑异或和大于零的充要条件是某一位不为零,那么可以拆位考虑。现在问题变成了给你一个0/1矩阵,让你在每行选一个数使最终异或和为1。

根据异或的性质可以发现选 0 不会影响异或结果,所以我们只需要找出来奇数个1即可。

我们先判断所有行中有 1 的行的个数,如果为奇数那每行都选 1 即可。如果个数为偶数那就找一个既有 0 也有 1 的行强行选 0 即可。


code:

#include <bits/stdc++.h>
using namespace std;
const int N = 500 + 10;
inline int read ()
{
int x = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar (); }
while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar (); }
return x * f;
}
int n, m;
int a[N][N];
void solve (int x, int d)
{
printf ("TAK\n");
for (int i = 1; i <= n; i++)
{
bool flag2 = false;
if (x != i)
{
for (int j = 1; j <= m; j++)
if ((a[i][j] >> d) & 1) { printf ("%d ", j); flag2 = true; break; }
}
else
{
for (int j = 1; j <= m; j++)
if (!((a[i][j] >> d) & 1)) { printf ("%d ", j); flag2 = true; break; }
}
if (!flag2) printf ("1 ");
}
}
signed main()
{
n = read (), m = read ();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) a[i][j] = read ();
for (int d = 10; d >= 0; d--)
{
int cnt = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if ((a[i][j] >> d) & 1) { cnt++; break; }
if (cnt & 1) { solve (0, d); return 0; }
else
{
for (int i = 1; i <= n; i++)
{
int cnt2 = 0;
for (int j = 1; j <= m; j++)
if ((a[i][j] >> d) & 1) cnt2++;
if (cnt2 && cnt2 < m) { solve (i, d); return 0; }
}
}
}
printf ("NIE\n");
return 0;
}

Problem for Nazar

解析:

题目大意

当\(i\)为奇数时,从集合\(\mathrm{A}\)中依次取数(取过了),当\(i\)为偶数时,从集合\(\mathrm{B}\)中向后取数。求黑板上第\(l\)个数到第\(r\)个数的和,答案对 \(10^9+7\)取余。

\(1 \le l,r \le 10^{18}\)


思路:

考虑把询问的区间按照奇数和偶数分成若干段,最多有 \(\log 10^{18}\) 个段,于是直接暴力即可。


code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
const int INV = 500000004;
const int mods = 1e9 + 7;
typedef pair <int, int> pii;
inline int read ()
{
int x = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar (); }
while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar (); }
return x * f;
}
int l, r;
int sum1, sum2;
int ans;
signed main()
{
l = read (), r = read ();
int sum = 0;
for (int i = 1; i <= 100; i++)
{
int lst = sum + 1;
sum += (1ll << (i - 1));
int b, e, cnt;
if (sum >= l)
{
if (i & 1)
{
b = 2 * (sum1 + 1 + ((l > lst) ? l - lst : 0)) - 1;
cnt = min (r, sum) - max (lst, l) + 1; cnt %= mods;
e = b + 2 * (cnt - 1);
ans += (b + e) % mods * cnt % mods * INV % mods;
}
else
{
b = 2 * (sum2 + 1 + ((l > lst) ? l - lst : 0));
cnt = min (r, sum) - max (lst, l) + 1; cnt %= mods;
e = b + 2 * (cnt - 1);
ans += (b + e) % mods * cnt % mods * INV % mods;
}
ans %= mods;
}
if (sum >= r || sum > 1e18) break;
if (i & 1) sum1 += (1ll << (i - 1));
else sum2 += (1ll << (i - 1));
}
printf ("%lld\n", ans);
return 0;
}

Stas and the Queue at the Buffet

解析:

题目大意:

共有 \(n\) 个人,第 \(i\) 个人有属性值 \(a_i,b_i\),现在要给这 \(n\) 个人重排顺序,设第 \(i\) 个人站在位置 \(j\),则他的不满意度是 \(a_i \times (j-1) + b_i \times (n-j)\)

最小化所有人的不满意度之和,求这个最小值


思路:

我们变一下式子:

\[\sum_{i=1}^{n}a_i\times (i-1)+b_i\times (n-i)\\
\sum_{i=1}^{n}a_i\times i-a_i-b_i\times i\\
n\times \sum_{i=1}^n b_i+\sum_{i=1}^na_i+\sum_{i=1}^{n}(a_i-b_i)\times i\\
\]

问题变为 \(\sum_{i=1}^n(a_i-b_i)\times i\) 的最小值,我们按照 \(a_i-b_i\) 从大到小排序即可。


code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
typedef pair <int, int> pii;
inline int read ()
{
int x = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar (); }
while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar (); }
return x * f;
}
int n;
struct node {
int x, y, z;
bool operator < (const node &A) const {
return z > A.z;
}
} a[N];
signed main()
{
n = read ();
for (int i = 1; i <= n; i++)
a[i].x = read (), a[i].y = read (), a[i].z = a[i].x - a[i].y;
sort (a + 1, a + n + 1);
int ans = 0;
for (int i = 1; i <= n; i++) ans += a[i].x * (i - 1) + a[i].y * (n - i);
printf ("%lld\n", ans);
return 0;
}

Number of Components

解析:

题目大意:

有一条 \(n(1 \leq n \leq 10^5)\) 个节点的链,编号相邻节点有边,每个点一个权值 \(a_i(1 \leq a_i \leq n)\),\(f(l,r)\)定义为权值在\([l,r]\) 的点中的连通块数量求 \(\sum_{l=1}^{n}\sum_{r=l}^{n} f(l,r)\) 。


思路:

考虑套路:连通块个数=所有权值在 \([l,r]\) 内的点的个数 \(-\) 连接他们的边的个数,这个是可以分开计算的。

我们考虑每个点对答案的贡献,不难发现对于 \(l\leq a_i \and a_i \leq r\) 的所有区间这个点都贡献了一次,答案为 \(a_i\times (n-a_i+1)\) ,这部分可以线性解决。

边权同理,我们把 \(a_i\rightarrow a_{i+1}\) 的边当作是一个点,类似二维数点,考虑 \(\forall l, r|l\in[1,\min(a_i,a_{i+1})],r\in[\max(a_i,a_{i+1}), n]\) 的 \((l,r)\) 都会对答案造成 \(-1\) 的贡献,一共贡献了 \(\min(a_i,a_{i+1})\times(n-\max(a_i,a_{i+1}+1))\) 次。

总联通块个数做差即可,时间复杂度线性。


code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair <int, int> pii;
inline int read ( )
{
int x = 0, f = 1;
char ch = getchar ( );
while (ch < '0' || ch > '9') {if (ch == '-') f = - 1; ch = getchar ( );}
while (ch >= '0' && ch <='9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar ( );}
return x * f;
}
int n, ans;
signed main()
{
n = read (); int lst, now;
for (int i = 1; i <= n; i++)
{
now = read ();
ans += (now * (n - now + 1));
if (i > 1) ans -= (min (lst, now) * (n - max (lst, now) + 1));
lst = now;
}
printf ("%lld\n", ans);
return 0;
}

Sonya and Informatics

解析:

题目大意:

给一个长度为 \(n\) \((n\leq 100)\) 的 \(0/1\) 串,进行 \(k\) \((k \leq 10^9)\) 次操作,每次操作随机选择两个位置 \(i,j\) \((1 \leq i < j \leq n)\),交换 \(i,j\) 上的数,求 \(k\) 次操作后,该 \(0/1\) 串变成非降序列的概率,答案对 \(10^9+7\) 取模。


思路:

考虑非降要求最终序列一定是前面是 0 后面是 1,假设 0 有 \(cnt\) 个,那么设 \(dp_{i,j}\) 表示交换了 \(i\) 次后前 \(cnt\) 个位置有 \(j\) 个 \(0\),那么有转移:

\[dp_{i+1,j+1}=dp_{i+1,j+1}+dp_{i,j}\times \frac{(cnt-j)^2}{\frac{n\times (n-1)}{2}}
\]

其中 \(\frac{n\times (n-1)}{2}\) 可以预处理逆元,\((cnt-j)^2\) 表示恰好选到前 \(cnt\) 个位置中的 1 的和后 \(n-cnt\) 中 0 的概率。

同时有转移:

\[dp_{i+1,j-1}=dp_{i+1,j-1}+dp_{i,j}\times \frac{j\times (n-cnt-(cnt-j))}{\frac{n\times (n-1)}{2}}
\]

\(j\times (n-cnt-(cnt-j))\) 表示恰好选到前 \(cnt\) 个位置中的 0 的和后 \(n-cnt\) 中 1 的概率。

剩下的转移到 \(dp_{i+1,j}\) 即可。

我们发现 \(n\leq 100\) 而 \(k\leq 10^9\) ,这显然可以矩快优化dp,我们设计如下矩阵:

\[A=\begin{bmatrix}
P(3,0)&P(1,0)&0&0&0&\cdots &0\\
P(2,1)&P(3,1)&P(1,1)&0&0&\cdots &0\\
0&P(2,2)&P(3,2)&P(1,2)&0&\cdots &0\\
0&0&P(2,3)&P(3,3)&P(1,3)&\cdots &0\\
\vdots & \vdots & \vdots &\vdots&\vdots & \ddots & \vdots \\
0&0&0&0&0&\cdots &P(3,cnt)\\
\end{bmatrix}
\]

其中 \(P(i,j)\) 表示第 \(i\) 类转移,转移前的前 \(cnt\) 个中有 \(j\) 个 0,那么有:

\[\begin{bmatrix}
dp_{i,0}&dp_{i,1}&dp_{i,2}&\cdots &dp_{i,cnt}
\end{bmatrix}
\times
A
=
\begin{bmatrix}
dp_{i+1,0}&dp_{i+1,1}&dp_{i+1,2}&\cdots &dp_{i+1,cnt}
\end{bmatrix}
\]

考虑设初始状态 \(dp_{0,x}=1\),其中 \(x\) 表示前 \(cnt\) 个中的 0 的数量,那么答案为:

\[\begin{bmatrix}
dp_{0,0}&dp_{0,1}&dp_{0,2}&\cdots &dp_{0,cnt}
\end{bmatrix}
\times
A^k
=
\begin{bmatrix}
dp_{m,0}&dp_{m,1}&dp_{m,2}&\cdots &dp_{m,cnt}
\end{bmatrix}
\]

则答案为 \(dp_{m,cnt}\)。

时间复杂度 \(\mathcal O(n^3\log k)\)。


code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100 + 10;
const int mods = 1e9 + 7;
typedef pair <int, int> pii;
inline int read ()
{
int x = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar (); }
while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar (); }
return x * f;
}
int n, m;
int a[N], cnt;
struct Matrix {
int h, r;
int m[N][N];
void init () { for (int i = 1; i <= h; i++) m[i][i] = 1; }
}ans;
Matrix operator * (const Matrix x, const Matrix y)
{
Matrix res;
res.h = x.h; res.r = y.r;
memset (res.m, 0, sizeof (res.m));
for (int i = 1; i <= x.h; i++)
for (int j = 1; j <= y.r; j++)
for (int k = 1; k <= x.r; k++)
(res.m[i][j] += ((x.m[i][k] * y.m[k][j]) % mods)) %= mods;
return res;
}
Matrix qpow (Matrix a, int p)
{
Matrix res;
res.h = res.r = a.h;
res.init ();
while (p) { if (p & 1) res = res * a; a = a * a; p >>= 1; }
return res;
}
int qpow2 (int a, int p)
{
int res = 1;
while (p) { if (p & 1) res = (res * a) % mods; a = (a * a) % mods; p >>= 1; }
return res;
}
signed main()
{
n = read (), m = read ();
for (int i = 1; i <= n; i++) a[i] = read (), cnt += !(a[i]);
ans.h = 1, ans.r = cnt + 1;
int cnt2 = 0;
for (int i = 1; i <= cnt; i++) cnt2 += !(a[i]);
ans.m[1][cnt2 + 1] = 1;
Matrix e;
e.h = e.r = cnt + 1;
int inv = qpow2 (n * (n - 1) / 2, mods - 2);
for (int i = 0; i <= cnt; i++)
{
int x, y, z;
x = ((cnt - i) * (cnt - i)) % mods;
y = (i * (n - cnt - cnt + i)) % mods;
z = (n * (n - 1) / 2 - x - y) % mods;
(x *= inv) %= mods; (y *= inv) %= mods; (z *= inv) %= mods;
e.m[i + 1][i + 1] = z; e.m[i + 1][i + 2] = x; e.m[i + 1][i] = y;
}
Matrix q = qpow (e, m);
ans = ans * q;
printf ("%lld\n", ans.m[1][cnt + 1]);
return 0;
}

Codeforces Round #553 (Div. 2)/codeforces1151的更多相关文章

  1. Codeforces Round #553 (Div. 2) D题

    题目网址:http://codeforces.com/contest/1151/problem/D 题目大意:给出n组数对,(ai , bi),调整这n组数对的位置,最小化 ∑(ai*( i -1)+ ...

  2. Codeforces Round #553 (Div. 2) C题

    题目网址:http://codeforces.com/contest/1151/problem/C 题目大意:给定奇数集和偶数集,现构造一个数组,先取奇数集中一个元素1,再取偶数集二个元素2,4,再取 ...

  3. Codeforces Round #553 (Div. 2) B题

    题目网址:http://codeforces.com/contest/1151/problem/B 题目大意:给定一个n*m的矩阵,问是否可以从每一行中选择一个数,使得这n个数异或大于0,如果可以还要 ...

  4. Codeforces Round #553 (Div. 2) A题

    题目网址:http://codeforces.com/contest/1151/problem/A 题目大意:给定一个由大写字母构成的字符串和它的长度,有这样的操作,使任意一个字母变成与其相邻的字母, ...

  5. Codeforces Round #553 (Div. 2) C

    C. Problem for Nazar time limit per test 1 second memory limit per test 256 megabytes input standard ...

  6. Codeforces Round #553 (Div. 2) E 贡献

    https://codeforces.com/contest/1151/problem/E 题意 一条长n的链,每个点上有值\(a[i]\),定义\(f(l,r)\)为该区间的\(值\)所代表的点留下 ...

  7. Codeforces Round #553 (Div. 2) C 等差数列求和 + 前缀和

    https://codeforces.com/contest/1151/problem/C 题意 有两个等差数列(1,3,5,..),(2,4,6,...),两个数列轮流取1,2,4,...,\(2^ ...

  8. Codeforces Round #553 (Div. 2)

    传送门 A. Maxim and Biology 题意: 给出一个串s,问最少需要多少步操作使得串s包含"ACTG"这个子串,输出最少操作次数: 题解: 枚举每个位置 i,求出将 ...

  9. Codeforces Round #553 (Div. 2) C. Problem for Nazar 数学

    题意:从奇数列 1 3 5 7 9 ....  偶数列2 4 6 8 10...分别轮流取 1 2 4 ....2^n 个数构成新数列 求新数列的区间和 (就一次询问) 思路:首先单次区间和就是一个简 ...

随机推荐

  1. SpringBoot(一、快速入门)

    1.SpringBoot简介   Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置, ...

  2. ApacheCon 2020 参会指南

    每年一度的 Apache 北美大会因为疫情的原因转到线上来举行了, 这次会议的主题是 ApacheCon@Home, 也就是说借助网络我们可以足不出户就可以参加 Apache 大会了.今年的会议为了针 ...

  3. 管理 MongoDB 用户和权限

    创建用户 创建用户的函数是:db.createUser(). 创建用户时,需要为该用户添加权限.可添加的权限以及说明: 权限 作用 read 允许用户读取指定数据库. readWrite 允许用户读写 ...

  4. mysql验证隔离级别

    mysql更改隔离级别 参考https://blog.csdn.net/qq_21299835/article/details/121189565 关闭mysql事务自动提交:set autocomm ...

  5. IDEA:库源与类的字节码不匹配

    在我配置pom.xml文件后,进行代码编辑,发现引入的方法并不是想要的内容,然后我就进入下载源码后进入到源码中发现我想要的方法和导入的jar包内的源码方法并不相同 ,于是到jar的存放地址中将其他版本 ...

  6. 日常问题: SQL优化

    日常开发中,除了开辟新项目,业务需求开发,一般还要做负责系统的日常运维.比如线上告警了,出bug了,必须及时修复.这天,运维反馈mysql cpu告警了,然后抓了该时间节点的慢sql日志,要开发分析解 ...

  7. 深度学习库 SynapseML for .NET 发布0.1 版本

    2021年11月 微软开源一款简单的.多语言的.大规模并行的机器学习库 SynapseML(以前称为 MMLSpark),以帮助开发人员简化机器学习管道的创建.具体参见[1]微软深度学习库 Synap ...

  8. 002-ImageNetClassificationDeep2017

    ImageNet classification with deep convolutional neural networks #paper 1. paper-info 1.1 Metadata Au ...

  9. RedHat Linux升级内核

    操作系统:Red Hat 6.4 内核文件:linux-3.10.1.tar.gz  https://www.cnblogs.com/cherish-sweet/p/newyum.html uname ...

  10. Windows Server体验之升级安装

    由于Windows Server的版本是每半年更新的,而微软对于产品的支持周期又是有限的.比如Windows Server 1803的主流支持只到2019年11月12日.也就是说,最多1年半,就需要更 ...