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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6273

思路:

记录乘2次数最小的值和乘3次数最小的值再用快速幂求解这个大多数人都能想到,比较棘手的就是n和m都是10^5,如果某个区间一个个的遍历去加1的话,会超时;这里用到了差分思想;

比较好的博客:https://www.cnblogs.com/COLIN-LIGHTNING/p/8436624.html

假设对两个区间操作  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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值