省赛热身赛9-J--Master of GCD (思维&&区间问题)
程序员文章站
2022-06-07 21:46:28
...
题目链接:http://acm.hnucm.edu.cn/vjudge/contest/view.action?cid=38#problem/J
【分析】 题意是给定长度的序列,且序列中的初值均为1,给出一系列的对某个区间的操作,使得该区间内的所有数字乘2或3,最后求该序列的最大公因数。
- 开两个数组,a、b,分别存储某个位置2的个数和3的个数。计数时,使左端点对应位置的对应数字加1,但右端点的后一个位置对应数字的个数-1,这一点很巧妙。
- 通过找出2出现的最少次数和3出现的最小次数,求出它们的乘积,就是1~n之间最大公约数。
- 参考:https://blog.csdn.net/Qin7_Victory/article/details/80030832
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int m,n;
#define mood 998244353
#define N 100010
int a[N],b[N];
long long int POW(int x,int s)
{
long long sum = 1;
while(s)
{
sum = sum*x%mood;
s--;
}
return sum;
}
int main()
{
int t;
int p,q,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i = 0;i < m; i++)
{
scanf("%d%d%d",&p,&q,&k);
if(k == 2)
{
a[p]++;
a[q+1]--; //方便统计有2的个数
}
else
{
b[p]++;
b[q+1]--;
}
}
int minn1 = a[1];
int minn2 = b[1];
for(int i = 2; i <= n; i++)
{
a[i] += a[i-1];
b[i] += b[i-1];
minn1 = min(minn1,a[i]);
minn2 = min(minn2,b[i]);
}
long long int sum = 0;
sum = POW(2,minn1);
sum = sum*POW(3,minn2)%mood;
printf("%lld\n",sum);
}
return 0;
}