省赛热身赛9-J--Master of GCD (思维&&区间问题)

题目链接:http://acm.hnucm.edu.cn/vjudge/contest/view.action?cid=38#problem/J

省赛热身赛9-J--Master of GCD (思维&&区间问题)_第1张图片

【分析】 题意是给定长度的序列,且序列中的初值均为1,给出一系列的对某个区间的操作,使得该区间内的所有数字乘2或3,最后求该序列的最大公因数。

  1. 开两个数组,a、b,分别存储某个位置2的个数和3的个数。计数时,使左端点对应位置的对应数字加1,但右端点的后一个位置对应数字的个数-1,这一点很巧妙。
  2. 通过找出2出现的最少次数和3出现的最小次数,求出它们的乘积,就是1~n之间最大公约数。
  3. 参考:https://blog.csdn.net/Qin7_Victory/article/details/80030832
#include
#include
#include
#include
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;
}

 

你可能感兴趣的:(ACM刷题册)