题意:
给你一个长度为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;
}