Codeforces Round #553 (Div. 2)/codeforces1151
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-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\),那么有转移:
\]
其中 \(\frac{n\times (n-1)}{2}\) 可以预处理逆元,\((cnt-j)^2\) 表示恰好选到前 \(cnt\) 个位置中的 1 的和后 \(n-cnt\) 中 0 的概率。
同时有转移:
\]
\(j\times (n-cnt-(cnt-j))\) 表示恰好选到前 \(cnt\) 个位置中的 0 的和后 \(n-cnt\) 中 1 的概率。
剩下的转移到 \(dp_{i+1,j}\) 即可。
我们发现 \(n\leq 100\) 而 \(k\leq 10^9\) ,这显然可以矩快优化dp,我们设计如下矩阵:
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,那么有:
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 的数量,那么答案为:
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的更多相关文章
- Codeforces Round #553 (Div. 2) D题
题目网址:http://codeforces.com/contest/1151/problem/D 题目大意:给出n组数对,(ai , bi),调整这n组数对的位置,最小化 ∑(ai*( i -1)+ ...
- Codeforces Round #553 (Div. 2) C题
题目网址:http://codeforces.com/contest/1151/problem/C 题目大意:给定奇数集和偶数集,现构造一个数组,先取奇数集中一个元素1,再取偶数集二个元素2,4,再取 ...
- Codeforces Round #553 (Div. 2) B题
题目网址:http://codeforces.com/contest/1151/problem/B 题目大意:给定一个n*m的矩阵,问是否可以从每一行中选择一个数,使得这n个数异或大于0,如果可以还要 ...
- Codeforces Round #553 (Div. 2) A题
题目网址:http://codeforces.com/contest/1151/problem/A 题目大意:给定一个由大写字母构成的字符串和它的长度,有这样的操作,使任意一个字母变成与其相邻的字母, ...
- Codeforces Round #553 (Div. 2) C
C. Problem for Nazar time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #553 (Div. 2) E 贡献
https://codeforces.com/contest/1151/problem/E 题意 一条长n的链,每个点上有值\(a[i]\),定义\(f(l,r)\)为该区间的\(值\)所代表的点留下 ...
- Codeforces Round #553 (Div. 2) C 等差数列求和 + 前缀和
https://codeforces.com/contest/1151/problem/C 题意 有两个等差数列(1,3,5,..),(2,4,6,...),两个数列轮流取1,2,4,...,\(2^ ...
- Codeforces Round #553 (Div. 2)
传送门 A. Maxim and Biology 题意: 给出一个串s,问最少需要多少步操作使得串s包含"ACTG"这个子串,输出最少操作次数: 题解: 枚举每个位置 i,求出将 ...
- Codeforces Round #553 (Div. 2) C. Problem for Nazar 数学
题意:从奇数列 1 3 5 7 9 .... 偶数列2 4 6 8 10...分别轮流取 1 2 4 ....2^n 个数构成新数列 求新数列的区间和 (就一次询问) 思路:首先单次区间和就是一个简 ...
随机推荐
- Dolphin Scheduler 1.2.0 部署参数分析
本文章经授权转载 1 组件介绍 Apache Dolphin Scheduler是一个分布式易扩展的可视化DAG工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程 ...
- 使用three.js(webgl)搭建智慧楼宇、设备检测、数字孪生——第十三课
老子云:有道无术,术尚可求,有术无道,止于术. 咱开篇引用老子的话术,也没其它意思,只是最近学习中忽有感悟,索性就写了上来. 这句话用现代辩证思维理解,这里的"道" 大抵是指方法论 ...
- 如何开发一款基于 vite+vue3 的在线表格系统(下)
在上篇内容中我们为大家分享了详细介绍Vue3和Vite的相关内容.在本篇中我们将从项目实战出发带大家了解Vite+Vue3 的在线表格系统的构建. 使用Vite初始化Vue3项目 在这里需要注意:根据 ...
- Dynamic CRM一对多关系的数据删除时设置自动删除关联的数据
在业务实体中主子表非常常见,然后子表可能有会有自己的子表或者多对多关系,在删除的业务场景下,删除主数据,剩余的子数据就成了脏数据, 之前的做法是,监听主表的删除事件,然后在插件中找到其下的子表数据然后 ...
- ADO.NET数据库开发
ADO.NET博客 ADO.NET - 张果 - 博客园 (cnblogs.com) ADO.NET官方 ADO.NET | Microsoft Docs EntityFrameWork 开始使用 ...
- Learn Dijkstra For The Last Time
博客链接:https://www.codein.icu/learn-dijkstra/ Introduction Dijkstra 算法是用于求解非负权图单源最短路的经典算法. 市面上的大部分教程都仅 ...
- Docker 拉取Nginx镜像 和运行
Docker 镜像拉取 docker pull [OPTIONS] NAME[:TAG|@DIGEST] 镜像拉取命令 OPTIONS说明: -a :拉取所有 tagged 镜像 --disable- ...
- Vue3中defineEmits、defineProps 是怎么做到不用引入就能直接用的
最近正在将一个使用单文件组件的 Options API 的 Vue2 JavaScript 项目升级为 Vue3 typescript,并利用 Composition API 的优势. 比如,下面这种 ...
- 尝试理解Linux容器进程与宿主机共享内核到底是什么意思?
背景 近期接触容器技术时,经常看到各类比较容器与虚拟机区别的文章中会提到:容器是共享宿主机的内核,而虚拟机则是拥有自己独立的内核,所以不可能在Linux上用容器运行windows,但是用虚拟机则可以. ...
- Linux 配置ODBC连接Oracle
在使用kdb_database_link 扩展插件连接Oracle数据库时,必须先配置ODBC,确保通过ODBC能连接Oracle数据库.以下是配置ODBC的过程. 一.安装ODBC 1.安装 [ro ...