倍增95pts WA#3 求条
查看原帖
倍增95pts WA#3 求条
1256325
XYHLYCHRIS楼主2024/11/13 20:51
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef string sg;
const ll NUM = 2e5 + 10, mod = 1e9 + 7;
ll n, m, q;// 同题意 
sg S;// 01串 

ll mu;// 每走一步相当于多走了mu圈; 
bool dat[3 * NUM];// 存01串,用于预处理 
struct TD {
	ll to, w; //从NUM走到to需要w步 
} aft[NUM];
TD mem[NUM][62];//从NUM出发走2^k步到达的点以及走的总位移 

int main() {
	cin.tie(0), cout.tie(0) -> sync_with_stdio(0);
	cin >> n >> m >> q;
	cin >> S, S = ' ' + S;//从1开 
	for (ll i = 1; i <= n; i++) {
		S[i] == '1'? dat[i] = true: dat[i] = false;
		dat[i + n * 2] = dat[i + n] = dat[i];
	}//存, 考虑 m > n 三倍长度就可以模拟出所有点能到的下一个等效点了(大概) 
	if (m > n) mu = m / n, m = m % n + n, mu = mu - m / n;// 计算 m > n 时,每一步相当于 转mu圈 
	ll p = m; 
	while (!dat[p]) p--;//找到末尾第一个 1 
	for (ll i = 1; i <= n; i++) {
		ll ext = i + m;
		if (dat[ext]) p = ext;
		p > i? aft[i].to = p: aft[i].to = i + 1;
		aft[i].w = aft[i].to - i + mu * n;
		aft[i].w %= mod;
		aft[i].to = aft[i].to - aft[i].to / n * n;
		if (!aft[i].to) aft[i].to = n;
	} // 预处理每一个位置 走一次 能去到的下一个 位置
	
	for (ll i = 1; i <= n; i++)
		mem[i][0].to = aft[i].to, mem[i][0].w = aft[i].w % mod;// 倍增数组初始化; 
	
	
	for (ll k = 1; k <= 61; k++) {
		for (ll p = 1; p <= n; p++) {
			mem[p][k].to = mem[mem[p][k - 1].to][k - 1].to;
			mem[p][k].w = (mem[p][k - 1].w + mem[mem[p][k - 1].to][k - 1].w) % mod;
		}
	}// 倍增 
	
	while (q--) {
		ll s, k;
		cin >> s >> k;
		ll ans = s;
		ans = ans % mod;
		s = s % n;
		if (s == 0) s = n;
		// 用 ans 记录 s, 把 s 处理到 n 以内 
		ll numb[63], p = 0;
		while (k) numb[p++] = (k & 1), k >>= 1;
		p--;// 2进制 
		ll tmp = 1ll << p;
		for (ll i = p; i >= 0; i--) {
			if (numb[i] == 1) {
				ans = (ans + mem[s][i].w) % mod;
				s = mem[s][i].to; 
			}
		}
		cout << ans << '\n';
	}
	return 0;
}
2024/11/13 20:51
加载中...