题意:
给你一个长度为n的全一数组s[n],进行m次操作,每次操作是在区间[l,r]中的所有a[i]乘x(x是2 or 3)。求s[n]的最大公约数。
题解:
如果直接n*m的话复杂度太高,所以需要优化,每次记录操作的起始位置和末位,通过,a[r]++和a[l+1]--,一个是操作的记录,一个是消除对a[l]之后数的影响。之后通过a[i+1]+=a[i]得到具体每个数的操作数,然后找出最小的操作值,之后用快速幂,求出所需的答案。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 100000 + 5; const int mod = 998244353; int a[N], b[N]; ll fun(ll a, ll b)//快速幂算法 { ll s=1; while(b>0){ if(b%2) s = (s * a) % mod; a = (a * a) % mod; b >>= 1; } return s; } int main() { int t, n, m, l, r, mul, min1, min2; ll ans; cin >> t; while(t--){ memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); min1 = min2 = mod; cin >> n >> m; for(int i=0;i<m;i++){//采用O(n)的查询方法,只记录头尾的操作 scanf("%d%d%d", &l, &r, &mul); if(mul == 2){ a[l] ++; a[r+1] --; } else{ b[l] ++; b[r+1] --; } } for(int i=1;i<=n;i++){ a[i] += a[i-1]; b[i] += b[i-1]; min1 = min(min1, a[i]); min2 = min(min2, b[i]); } ans = fun(2, (ll)min1); ans = (ans * fun(3, (ll)min2)) % mod; cout << ans<<endl; } return 0; }