1. 程式人生 > >HDU 6273 Master of GCD 【差分思想+快速冪】

HDU 6273 Master of GCD 【差分思想+快速冪】

思路:

記錄乘2次數最小的值和乘3次數最小的值再用快速冪求解這個大多數人都能想到,比較棘手的就是n和m都是10^5,如果某個區間一個個的遍歷去加1的話,會超時;這裡用到了差分思想;

假設對兩個區間操作  1 到 5 ,+1, 2 到 3, + 1,那麼有 

1 0 0 0 0 -1 (1到5區間+1) , 1 1 0 -1 0 -1 (2到3區間+1) ;

我們從1開始依次做  a[i] += a[i-1] ; 可以發現遍歷一遍就能還原我們要的結果  1 2 2 1 1 0 ;這就是差分思想,即使n和m再大都無所畏懼;

//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>

using namespace std;
//using namespace __gnu_pbds;

//------------------ 巨集定義 --------------------------------

#define IOS ios::sync_with_stdio(false); cin.tie(0);
#define REP(i,n) for(int i=0;i<n;++i)

//------------------- 預備函式 ------------------------------
int read(){
    int r=0,f=1;char p=getchar();
    while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
    while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}
int dcmp (double x, double y) {
    if (fabs(x-y) < 1e-6) return 0;
    if (x > y) return 1; return -1;
}

//------------------- 常量+宣告 ------------------------------------------

//typedef tree<pair<long long,int>,null_type,less< pair<long long,int> >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
const int Maxn = 1e5+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
const int Mod = 998244353;
const double PI = acos(-1.0);
const double eps = 1e-6;

//-------------------------------------------------------------------------

ll two[Maxn], three[Maxn];

int pow_mod (int a, ll n) {
    if (n == 0) return 1;
    int x = pow_mod (a, n/2);
    ll ans = (ll)x*x % Mod;
    if (n & 1) ans = ans*a % Mod;
    return (int)ans;
}

int main (void)
{
    int t, n, m;
    scanf ("%d", &t);
    while (t--) {
        scanf ("%d%d", &n, &m);
        memset (two, 0, sizeof (two));
        memset (three, 0, sizeof (three));
        int L, R, x;
        for (int i = 0; i < m; ++i) {
            scanf ("%d%d%d", &L, &R, &x);
            if (x == 2) {
                two[L]++; two[R+1]--;
            } else {
                three[L]++; three[R+1]--;
            }
        }
        ll m1 = two[1], m2 = three[1];
        for (int i = 2; i <= n; ++i) {
            two[i] += two[i-1]; three[i] += three[i-1];
            m1 = min (m1, two[i]); m2 = min (m2, three[i]);
        }
        int ans = pow_mod (2, m1);
        ans = (ll)ans * pow_mod (3, m2) % Mod;
        printf ("%d\n", ans);
    }
    return 0;
}