ccpc2017杭州 J Master of GCD

题意:

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

猜你喜欢

转载自blog.csdn.net/Endeavor_jianjian/article/details/79971960