HDU-6273 GCDのマスター(素因数分解定理の適用)

HDU-6273 GCDのマスター(素因数分解定理の適用)

ここに画像の説明を挿入


題名:

  • Tグループデータを提供する
  • データの各グループの最初の行にnとmを入力します。これは、長さがnで初期値が1の配列に対してm個の操作が実行されることを意味します。
  • 各操作に3つの数値L、R、opを入力します。opは2または3のみです。これは、LからRまでの区間の各数値を意味します。a[i] = a [i] * op、i = 2,3
  • m回の操作後のこれらのn個の最大公約数は何ですか?

アイデア:

  • n個の最大公約数を見つけるには、これらのn個の数を素因数に分解し、n個の分解式に現れたすべての素因数aと素因数の最小公約数pを見つけて、すべてを乗算します。pは最大公約数
  • 質問の意味から、各数値の初期値は1であり、素因数は2または3のみです。したがって、a [i]に2を掛けた回数と3を掛けた回数を記録することは、aを分解することに相当します。 [i]素因数に、そして最後に2の最小の累乗と3の最小の累乗を数え、次に乗算します(速い累乗を使用し、残りを取ることを忘れないでください)
  • a [i]に2と3を掛けた回数を数える方法は?私は線をスキャンするという考えを使用し、book配列を使用してカウントし、book [L] ++、book [R + 1] –、そして最後にプレフィックスの合計を計算します

撸コード:

#include<math.h>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
long long book[4][100010];
long long mod=998244353;
ll Quick_Power(ll a,ll b)//快速幂
{
    
    
    ll res = 1;
    a %= mod;
    while(b){
    
    
        if(b&1){
    
    
            res = (res * a) % mod;
        }
        a = (a * a) % mod;
        b >>= 1;
    }
    return res%mod;
}
int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--){
    
    
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n+1;i++){
    
    
			book[2][i]=book[3][i]=0;
		}
		int r,l,tag;
		for(int i=0;i<m;i++){
    
    
			scanf("%d%d%d",&l,&r,&tag);
			book[tag][l]++;
			book[tag][r+1]--;
		}
		
		for(int i=1;i<=n;i++){
    
    
			book[2][i]+=book[2][i-1];
			book[3][i]+=book[3][i-1];
			/*由于初始值为 1 ,所以每个数的素因子只有 2 和 3 ,
			通过该步骤得出每个数的素因子的幂次,找到2的最小幂次 和 3 的最小幂次,
			乘积就是最大公约数  */
//			printf("%d  |   %d\n",book[2][i],book[3][i]);  
			
		}
		long long mina=0x3f3f3f3f,minb=0x3f3f3f3f;
		for(int i=1;i<=n;i++){
    
    
			mina=min(mina,book[2][i]);
			minb=min(minb,book[3][i]);
		}
		long long temp1=Quick_Power(2,mina);
		long long temp2=Quick_Power(3,minb);
		printf("%lld\n",(temp1*temp2)%mod);
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/DREAM_yao/article/details/109255690