首页 > 其他分享 >AtCoder Beginner Contest 200 F Minflip Summation

AtCoder Beginner Contest 200 F Minflip Summation

时间:2023-05-17 13:23:19浏览次数:70  
标签:AtCoder typedef matrix Beginner 200 int res ll ++

洛谷传送门

AtCoder 传送门

显然的策略:选择全部 \(0\) 段变成 \(1\),或选择全部 \(1\) 段变成 \(0\)。

归纳可得一般性的结论:设字符串中 \(s_i \ne s_{i+1}\) 的位置数为 \(k\),答案为 \(\left\lceil\frac{k}{2}\right\rceil\)。

因为在模意义下不能上取整,考虑记 \(k\) 的奇偶性(这样统计答案的时候就知道答案是 \(\frac{k}{2}\) 还是 \(\frac{k+1}{2}\)),然后 dp。设 \(f_{i,0/1,0/1}\) 为前 \(i\) 个字符中,\(k\) 的奇偶性,\(s_i\) 填的数,\(k\) 的总和。类似地设 \(g_{i,0/1,0/1}\) 表示方案数。转移是 trivial 的。

因为 \(K \le 10^9\),考虑把转移写成 \(8 \times 8\) 的矩阵乘法形式,预处理第一个 copy 的 dp 值,做一遍矩阵快速幂就行。

时间复杂度 \(O(n + 8^3 \log K)\)。

code
// Problem: F - Minflip Summation
// Contest: AtCoder - KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)
// URL: https://atcoder.jp/contests/abc200/tasks/abc200_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 100100;
const ll mod = 1000000007;
const ll inv2 = (mod + 1) / 2;

struct matrix {
	ll a[8][8];
	matrix() {
		mems(a, 0);
	}
} ma[maxn], I;

inline matrix operator * (const matrix &a, const matrix &b) {
	matrix res;
	for (int i = 0; i < 8; ++i) {
		for (int j = 0; j < 8; ++j) {
			for (int k = 0; k < 8; ++k) {
				res.a[i][j] = (res.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
			}
		}
	}
	return res;
}

inline matrix qpow(matrix a, ll p) {
	matrix res = I;
	while (p) {
		if (p & 1) {
			res = res * a;
		}
		a = a * a;
		p >>= 1;
	}
	return res;
}

int n, m, id[2][2][2];
ll f[maxn][2][2], g[maxn][2][2];
char s[maxn];

void solve() {
	for (int i = 0; i < 8; ++i) {
		I.a[i][i] = 1;
	}
	scanf("%s%d", s + 1, &m);
	n = strlen(s + 1);
	for (int i = 0; i < 2; ++i) {
		for (int j = 0; j < 2; ++j) {
			for (int k = 0; k < 2; ++k) {
				id[i][j][k] = i * 4 + j * 2 + k;
			}
		}
	}
	if (s[1] == '0' || s[1] == '?') {
		g[1][0][0] = 1;
	}
	if (s[1] == '1' || s[1] == '?') {
		g[1][0][1] = 1;
	}
	for (int i = 2; i <= n; ++i) {
		for (int j = 0; j < 2; ++j) {
			for (int x = 0; x < 2; ++x) {
				for (int y = 0; y < 2; ++y) {
					if (s[i] != '?' && s[i] != '0' + y) {
						continue;
					}
					int nj = j ^ (x ^ y);
					f[i][nj][y] = (f[i][nj][y] + f[i - 1][j][x]) % mod;
					if (x ^ y) {
						f[i][nj][y] = (f[i][nj][y] + g[i - 1][j][x]) % mod;
					}
					g[i][nj][y] = (g[i][nj][y] + g[i - 1][j][x]) % mod;
				}
			}
		}
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j < 2; ++j) {
			for (int x = 0; x < 2; ++x) {
				for (int y = 0; y < 2; ++y) {
					if (s[i] != '?' && s[i] != '0' + y) {
						continue;
					}
					int nj = j ^ (x ^ y);
					++ma[i].a[id[0][j][x]][id[0][nj][y]];
					if (x ^ y) {
						++ma[i].a[id[1][j][x]][id[0][nj][y]];
					}
					++ma[i].a[id[1][j][x]][id[1][nj][y]];
				}
			}
		}
	}
	matrix a = I, b;
	for (int i = 1; i <= n; ++i) {
		a = a * ma[i];
	}
	for (int i = 0; i < 2; ++i) {
		for (int j = 0; j < 2; ++j) {
			b.a[0][id[0][i][j]] = f[n][i][j];
			b.a[0][id[1][i][j]] = g[n][i][j];
		}
	}
	matrix res = b * qpow(a, m - 1);
	ll ans = 0;
	for (int i = 0; i < 2; ++i) {
		ans = (ans + (res.a[0][id[0][1][i]] + res.a[0][id[1][1][i]]) % mod * inv2 % mod) % mod;
		ans = (ans + res.a[0][id[0][0][i]] * inv2 % mod) % mod;
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,typedef,matrix,Beginner,200,int,res,ll,++
From: https://www.cnblogs.com/zltzlt-blog/p/17408450.html

相关文章

  • 2000行代码,再不学习就老了
    前段时间,利用业余摇摇晃晃的写了1600行代码然后就有了AutoLink 最近经过更新,代码量升至2000左右,功能变得更加完善单击关键字显示帮助信息输入时自动补全提示越来越完善的用户指南用户指南简介安装与启动如何创建测试项目如何运行测试项目如何管理用例顺序使用关键字快捷键关键字概......
  • SIEMENS/西门子西门子S7-1200 PID温度控制程序,PID参数经过预调节和精确调节之后得出,
    SIEMENS/西门子西门子S7-1200PID温度控制程序,PID参数经过预调节和精确调节之后得出,程序采用博图V16高级版编写,适合用于不带冷却功能的模具加热生产工艺上,项目上运用已稳定工作多时,带详细注释,可进行二次开发和扩展,也可直接使用!!本程序采用博图V16编写,需要博图版本高于V16,版本低于V......
  • SQL Server(2008版)还原数据库备份 修改表结构
    昨天接到个小活,前公司一个项目中,有个功能不太正常,需要帮忙排查原因并解决,于是在本地部署环境,还原数据库并运行程序。由于已经从前公司离开3年有余,到这边以后主要是做导航算法相关开发,基本不使用数据库,即便用到的地方也都是Mysql和MongoDB,MSSQLServer被淡忘,操作过程中明明记得有个......
  • Step7-Mricro/win S7-200 485轮询 西门子485
    Step7-Mricro/winS7-200485轮询西门子485modbusRTU200ModbusRTU通信S7-200与最大32个从站RS485主站程序,程序块自动轮询,无需编写轮询逻辑。程序为标准块间接寻址设计思路,可复制使用,可建成库,用时调出即可!程序可用于西门子S7-200.Mo......
  • 判断 101-200 之间有多少个素数,并输出所有素数。
    判断101-200之间有多少个素数,并输出所有素数。#如果一个数N不是素数,对于从2到(N-1)的所有数,N依次除以2到(N-1)的所有数,一定会出现余数≠0#取出101-200之间的所有素数,放到一个列表中,可以计算出素数的个数并输出所有素数primenum_list=[]fornumberinrange(101,201):......
  • AtCoder Regular Contest 160 D Mahjong
    洛谷传送门AtCoder传送门搞笑题,我不会做,我更搞笑。考虑逆序操作,即初始有一个全\(0\)序列,每次单点加\(k\)或者长为\(k\)区间加\(1\)。考虑把一个操作集合唯一对应到一个最终序列,不难发现只要限制每个区间加\(1\)的次数\(<k\)即可。因为如果正序操作,加上了限制,每个......
  • AtCoder Beginner Contest 301 F Anti-DDoS
    洛谷传送门AtCoder传送门考虑分类计数,讨论“没有DD”、“有DD无o”、“有DDo无S”三种情况。没有DD,枚举有几种大写字母出现过;剩下两种情况,考虑设\(f_{i,0/1}\)分别表示两种情况的方案数。\(f_{i,0}\)可以从\(f_{i-1,0}\)填大写字母转移,也可以枚举第一个出现两......
  • Atcoder Regular Contest 101
    F-RobotsandExits\(n\)个人,\(m\)个出口在一条数轴上,坐标是正整数。你每次可以让所有人向左或向右一步,人在某个出口上后就离开。求多少种操作的方案使得人全部走光。两个方案相同当且仅当存在至少一个人在两次操作序列进行完成后从不同的出口消失。对\(10^9+7\)取模。\(1......
  • AtCoder Beginner Contest 223 G Vertex Deletion
    洛谷传送门AtCoder传送门设\(f_{u,0/1}\)为\(u\)的子树,\(u\)是否在匹配内的最大匹配数。注意到对于一个匹配,在它深度较浅的点上才会被计入答案。转移大概是\(f_{u,0}\)取\(\sum\limits_{v\inson_u}\max(f_{v,0},f_{v,1})\),\(f_{u,1}\)要从儿子中选一个\(f_{v,0......
  • panjf2000/ants:一个高性能的 goroutine 池管理工具
    简介ants是一个高性能的goroutine池,实现了对大规模goroutine的调度管理、goroutine复用,允许使用者在开发并发程序的时候限制goroutine数量,复用资源,达到更高效执行任务的效果。goroutine相比于线程来说,有着更轻量、资源占用更少、切换速度更快、无线程上下文切换开销更少等......