CodeTON Round 3 (C.差分维护,D.容斥原理)
C. Complementary XOR
题目大意:
给你两个01串ab,问你是否可以通过一下两种操作在不超过n+5次的前提下将两个串都变为0,同时需要输出可以的操作方案
- 选择一个区间[l,r]
- 将串a的[l,r]翻转(0 \(\rightarrow\) 1,1 $\rightarrow$0), 同时将b的[1,l)和(r,n]区间翻转
解题思路:
通过写两组样例,我们可以尝试这种思路,因为我们需要输出可以的操作方案 ,我们很难去考虑同时操作a,b两个串的操作,所以我们尝试只考虑a串。将a串的全部0变成1,观察b串经过这种操作后的结果。
我们可以发现,如果a串全为1,那b串此时有三种可能:
- 全为0
- 全为1
- 即含1,又含0
我们发现状况1可以通过对a进行一次[1,n]操作使a,b都为0
状况2可以通过对a进行一次[1,1],[2,n]操作使a,b都为0(观察最后一个样例)
但是状况3我们没有任何办法使得a,b都为0
自此整个题目分析完毕,我们只需要记录让a全部为1的操作对b的影响,最后看b串是否属于情况1,2即可
我们观察操作对b的影响是对[1,l)和(r,n]整个的影响,所以可以理解为对[1,l)和(r,n]操作次数都+1,因为翻转2次等于没翻转,(只有翻转奇数次才会真的翻转),因为是对整个区间+1,所以就可以考虑用差分维护(O(1))
操作影响如下,假如选择的区间为[i,i],对b的影响就是b[1] += 1;b[i]-=1;b[i+1] += 1;
代码实现:
# include<iostream>
# include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e5 + 10, inf = 1e9 + 7;
int b[N];
int a[N];
void solve() {
int n;
cin>>n;
for(int i = 1;i <= n+1;++i) b[i] = a[i] = 0;
string s1,s2;
cin>>s1>>s2;
s1 = "?"+s1;
s2 = "?"+s2;
bool ok = true;
vector<pair<int,int>> ans;
for(int i = 1;i <= n;++i)//看看两个串是不是本身就为全0
{
if(s1[i]!= '0'||s2[i] != '0') {
ok = false;
break;
}
}
if(ok){
cout<<"YES"<<endl;
cout<<0<<endl;
return;
}
for(int i = 1;i <= n;++i){
if(s1[i] == '0'){
ans.push_back({i,i});
b[1] += 1;//差分维护对b的影响
b[i]-=1;
b[i+1] += 1;
}
}
for(int i = 1;i <= n;++i){
a[i] = a[i-1]+b[i];//前缀和计算对每个位置的影响
}
for(int i = 1;i <= n;++i){
if(a[i]&1){//如果操作次数为奇数则进行变化
if(s2[i] == '0') s2[i] = '1';
else s2[i] = '0';
}
}
for(int i = 1;i <= n;++i){
if(s2[i] != s2[1])//非(全0或者全1)
{
cout<<"NO"<<endl;
return;
}
}
if(s2[1] == '0'){
ans.push_back({1,n});
}
else{
ans.push_back({1,1});
ans.push_back({2,n});
}
cout<<"YES"<<endl;
cout<<ans.size()<<endl;
for(auto [x,y]:ans){
cout<<x<<" "<<y<<endl;
}
}
int tt;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
tt = 1;
cin >> tt;
while (tt--)solve();
return 0;
}
D. Count GCD
题目大意:
对于给定n,m,给你一个含n个数的数组,数组中每个数的取值范围在[1,m]
问能构造多少组数组b满足一下条件:
- b[i] \(\in\)[1,m]
- gcd(b[1],b[2],...,b[i]) = a[i]
解题思路:
基本看到构造多少组b满足以上条件的就可以考虑原数组每一位的贡献了,类似于组合数学是每一位的贡献的积为总的组数
所以总的框架就是
int ans = 1;
for(int i = 2;i <= n;++i){
if(a[i] == a[i-1]){
int t = m/a[i];//当前这一位的贡献
ans = ans*t%mod;//总贡献
}
else{
int t = cal(a[i-1]/a[i],m/a[i]);//当前这一位的贡献
ans = ans*t%mod;
}
}
cout<<ans<<endl;
然后考虑每一位的贡献是怎么样的形式
我们写两组数据大概可以的到一下的思路:
因为是前缀gcd,所以明显每个数的质因子是不断变小的,然后我们如果要求解b[i]
就有如下思路:gcd(a[i-1],b[i]) = a[i]
那我们要求的其实就是a[i]的倍数,比如a[i-1] = 6,a[i] = 3,那能够满足g(6,b[i]) = 3的只有3的倍数(3,6,9,12,15.....k*3<= m),但是我们很容易就发现6,12是不能选的gcd(6,6||12) = 6,同理如果m/a[i] (所有的倍数)包含a[i-1]/a[i]的质因子的时候就都不能选
所以,问题可以转化为:从[1,m/a[i]]中选与(a[i-1]/a[i])互质的数有多少个
于是引入容斥原理:
Tot = C\(_n\)\(^1\) - C\(_n\)\(^2\) + C\(_n\)\(^3\).....
用韦恩图表示如下:
所以我们就考虑用总的(m/a[i])-res(所有与a[i-1]/a[i]不互质的数的并集)
之所以取与a[i-1]/a[i]不互质的数的并集是因为它比较好表示,用(m/a[i])/(选中的因子的积)就是不互质数的数量
比如从1,2,3,4,5,6中求与2,3不互质的数
实际上就是6-(2的倍数({2,4,6} $\rightarrow$6/2 = 3)+3的倍数({3,6} $\rightarrow$6/3 = 2)-(2*3)的倍数({6} $\rightarrow$6/6 = 1)) = 6-3-2+1 = 2{1,5}
代码实现:
# include<iostream>
# include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e5 + 10, mod = 998244353;
int a[N];
//在[1,top]范围内,找和n互质的数的个数
int cal(int n,int top){
vector<pair<int,int>> divisors;//质因子
for(int i = 2;i*i<=n;++i){
if(n%i == 0){
int s = 0;
while(n%i == 0) n/=i,s++;
divisors.push_back({i,s});//i的s次
}
}
if(n>1) divisors.push_back({n,1});
int res = 0,m = divisors.size();
for(int i = 1;i< (1<<m);++i)//二进制模拟第j个元素选还是不选
{
int t = 1,s = 0;
for(int j = 0;j < m;++j){
if(i>>j&1){
if(t*divisors[j].first>top){
t = -1;
break;
}
t *= divisors[j].first;
s++;
}
}
if(t != -1)
{
if(s%2) res += top/t;//如果选了奇数个元素就是加
else res -= top/t;//偶数个元素是减
//从容斥原理可以得到
}
}
return top-res;
}
void solve() {
int n,m;
cin>>n>>m;
for(int i = 1;i <= n;++i) cin>>a[i];
for(int i = 2;i <= n;++i){
if(a[i-1]%a[i]){
cout<<0<<endl;
return;
}
}
int ans = 1;
for(int i = 2;i <= n;++i){
if(a[i] == a[i-1]){
ans = ans*(m/a[i])%mod;
}
else{
int t = cal(a[i-1]/a[i],m/a[i]);
ans = ans*t%mod;
}
}
cout<<ans<<endl;
}
int tt;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
tt = 1;
cin >> tt;
while (tt--)solve();
return 0;
}
CodeTON Round 3 (C.差分维护,D.容斥原理)的更多相关文章
- Codeforces Round #258 E Devu and Flowers --容斥原理
这题又是容斥原理,最近各种做容斥原理啊.当然,好像题解给的不是容斥原理的方法,而是用到Lucas定理好像.这里只讲容斥的做法. 题意:从n个容器中总共取s朵花出来,问有多少种情况.其中告诉你每个盒子中 ...
- Experimental Educational Round: VolBIT Formulas Blitz K. Indivisibility —— 容斥原理
题目链接:http://codeforces.com/contest/630/problem/K K. Indivisibility time limit per test 0.5 seconds m ...
- Codeforces Global Round 2 D 差分 + 前缀和 + 二分
https://codeforces.com/contest/1119/problem/D 题意 有n个数组,每个数组大小为\(10^{18}+1\)且为等差数列,给出n个数组的\(s[i]\),q次 ...
- CodeTON Round 3 (Div. 1 + Div. 2, Rated, Prizes!) A-D
比赛链接 A 题解 知识点:贪心. 注意到 \(a[1] \neq 1\) , \(1\) 永远不可能换到前面:\(a[1] = 1\) 可以交换后面任意元素. 时间复杂度 \(O(n)\) 空间复杂 ...
- BZOJ 4999 LCA树状数组差分维护DFS序
Description 给一颗树,每个节点有个初始值 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x 2. Q i j x(0<=x<2 ...
- CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!) A ~ D
A. 给定一个序列,对于任意1<=k<=n 都满足|ai−ak|+|ak−aj|=|ai−aj|, 找满足条件的i和j并输出 思路: 观察样例,发现输出的是最大值和最小值,那么猜答案是最大 ...
- CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) A-E
比赛链接 A 题解 知识点:思维,模拟. 发现 \(b\) 串第一个字符是 \(1\) 则只能使用 max , \(0\) 则只能使用 min ,随后只需要模拟到 \(a\) 串剩余 \(m\) 个字 ...
- UOJ236 IOI2016 Railroad 差分、欧拉回路、最小生成树
传送门 将"进入路段时速度\(\leq s_i\)"转换为:"进入路段时速度恰好等于\(s_i\),并且铺设铁轨有加速和减速两种,加速无需代价,减速每\(1 km/h\) ...
- BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)
某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...
随机推荐
- centos 安装ftp服务BUG
安装完成之后匿名可登录,但是先创建的用户名和密码无法登录,最后排查原因是/etc/pam.d/vsftpd 文件注释掉第四行 auth required pam_shells.so
- JS/java实现QQ空间自动点赞
使用方法: 1:进入QQ空间 2:复制下面代码 3:按F12或右键审查元素 进入控制台 也就是console 4:粘贴 回车键 喝口水 5:如果嫌慢的话可以 修改这段代码. window.setI ...
- 【读书笔记】15《The Bridge of Madison County》
廊桥遗梦(梅丽尔·斯特里普主演) 罗伯特·詹姆斯·沃勒 99个笔记 The Beginning 美[|diˈklainz]v 辞谢,谢绝(邀请等)( decline的第三人称单数 );(道路.物体 ...
- KingbaseES 多列分区的方法与性能
前言 对于多列分区,可以选择单级多列的范围分区,也可以选择范围加子分区的方式.但二者在不同场景下对于性能是有差异的,这里的性能差异主要是分区裁剪引起的差异. 例子 创建两张分区表,采取不同的分区策略: ...
- KingbaseES 如何开启并进入数据库
关键字: KingbaseES.sys_ctl.ksql 一.数据库启动前环境检测 1.1 查看kingbase用户环境变量配置 图1-1 查看.bashrc环境变量配置 1.2 应用环境变量 [ki ...
- Java中如何创建不可变(immutable)类
什么是不可变类 1. 不可变类是指类的实例一经创建完成,这个实例的内容就不会改变. 2. Java中的String和八个基本类型的包装类(Integer, Short, Byte, Long, Dou ...
- Fast.Framework ORM 试用
简介 Fast.Framework 是一款基于 .NET 6 封装的轻量级ORM框架,支持多种数据库(SQL Server.Oracle.MySQL.PostgreSQL.SQLite). 优点 性能 ...
- 2020年12月-第01阶段-前端基础-HTML CSS 项目阶段(一)
品优购项目(一) 目标: 能会引入ico图标 能简单看懂网站优化的三大标签 能使用字体图标 ( 重点 ) 能说出我们css属性书写顺序 1. 品优购项目介绍 项目名称:品优购 项目描述:品优购是一个电 ...
- 安装vm,在vm中安装windows10操作系统。
步骤:双击打开虚拟机文件 根据向导安装 下一步 然后等待安装 安装好了后点击许可证 ZF3R0-FHED2-M80TY-8QYGC-NPKYF YF390-0HF8P-M81RQ-2DXQE-M2U ...
- 使用prometheus + granafa 监控mysql主从
若主从同步数据库未同步默认的mysql表,则也需要在从库上创建mysql用户mysqld_exporter用来收集监控数据 mysqld_exporter安装部署 这里采取的是mysqld_expor ...