题意:
给出T组数据(1 <= T <= 10),每组数据中,有两个数n(1 <= n <= 10^5)和 m (1 <= m <= 10^5)。其中 n 表示有n个由1组成的数, m表示下面给出m组数据,每组数据由 p q k 组成。表示区间p 到 q,增大k倍。(k 等于2 或者 3).输出这n个数最终的最大公约数。由于数据比较大,因此需要mod 998244353。
测试数据
/*
2
5 3
1 3 2
3 5 2
1 5 3
6 3
1 2 2
5 6 2
1 6 2
*/
思路:
这道题其实可以根据区间端点来查找。通过分别统计每个1~n个位置中,2的个数以及3的个数。
if(k == 2)
{
a[p]++;
a[q+1]--; //方便统计有2的个数
}
else
{
b[p]++;
b[q+1]--;
}
(考虑到区间问题,所以这里需要注意两种情况 2~5, 和 6 ~ 7)这两种情况,一种数正好在区间内,另一种,正好再区间外,为了把1~n全部的联系在一起,所以在统计2和3 的个数的时候,只是将第一个端点个统计的,最后一个端点的下一个数先提前减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]);
}
最后通过找出2出现的最少次数和3出现的最小次数,求出它们的乘积,就是1~n之间最大公约数。
#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;
}