首页 > 其他分享 >ZROJ237 小T的gcd - 数论 -

ZROJ237 小T的gcd - 数论 -

时间:2022-12-07 00:44:44浏览次数:73  
标签:tmp 质因数 gcd 数论 int lst maxn include ZROJ237

题目链接:http://zhengruioi.com/problem/237

题解:
首先第一问很简单,如果n个数的gcd为1,答案就是 n 否则为 -1
考虑第二问,发现由于 lcm 是小于等于乘积的,若相等则必然两两互质
按照质因数考虑,也就是对于答案区间来说,对于所有的质因数,这个区间至多有一个该质因数的倍数
因此可以从后往前扫一遍,每次分解质因数,然后统计一下上一次出现该质因数是在什么位置,对于位置取min即可
暴力分解大概是略小于\(O(n \sqrt{n})\),可以有 70pts
这里有一个小 trick:每次分解质因数的时候实际上我只需要知道当前数的最小质因子是什么就行了,这就可以线性筛求出,由于 \(2*3*5*7*11*13*17*19 > 1e6\),因此时间复杂度为 \(O(8n)\)
当然,注意到当区间左端点左移的时候,区间右端点一定也左移,因此可以双指针扫一下,时间复杂度也是对的

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 1e6+5;

int notpm[maxn], pm[maxn], pcnt = 0, curv[maxn], lea[maxn];

void xxs(){
	notpm[1] = 1;
	for(int i=2;i<=maxn-5;i++){
		if(!notpm[i])pm[++pcnt]=i, curv[i] = pcnt, lea[i] = pcnt;
		for(int j=1;j<=pcnt&&1ll*pm[j]*i<=maxn-5;j++){
			notpm[i*pm[j]] = 1;
			lea[i*pm[j]] = j;
			if(i%pm[j] == 0)break;
		}
	}
}

int n,a[maxn], lst[maxn], rightmost[80005], cs;
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
void solve(){
	int ans = -1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	int gd = a[1];
	for(int i=2;i<=n;i++)gd=gcd(gd, a[i]);
	memset(rightmost, 0x3f, sizeof rightmost);
	lst[n+1] = n + 1;
	for(int i=n;i>=1;i--){
		lst[i] = lst[i+1];
		int tmp = a[i];
		vector<int>curpm;
		while(tmp != 1){
			curpm.push_back(lea[tmp]);
			int cc = pm[lea[tmp]];
			while(tmp%cc == 0)tmp /= cc;
		}
		for(int u : curpm){
			lst[i] = min(lst[i], rightmost[u]);
			rightmost[u] = i;
		}
		ans = max(ans, lst[i] - i + 1 - 1); 
	}
	printf("Case %d: %d ",++cs,gd == 1 ? n : -1);
	if(ans == 1)puts("-1");
	else printf("%d\n",ans);
}

signed main(){
	xxs();
	int te;scanf("%d",&te);
	while(te--)solve();

	return 0;
}

标签:tmp,质因数,gcd,数论,int,lst,maxn,include,ZROJ237
From: https://www.cnblogs.com/SkyRainWind/p/16961914.html

相关文章

  • 每日一题-数论
    数论Description\[给定n,m\in[1,1e9]\\找到使得res=n\cdotx末尾零的个数最多,结果最大的x,其中,\\x\in[1,m]\]Solution容易联想到经典题目,求阶乘末尾零......
  • 《一些特殊的数论函数求和问题》阅读笔记
    好至少它教会了我如何把质数求和转化成积分的渐进对着\(\pi(x)\)微就行了然后直接\(u\textdv=uv-v\textdu\)18.3k……阿巴阿巴引言这玩意挺常见的。而且你会......
  • 初级数论1:(扩展)欧几里得算法
    初级数论第一节:欧几里得算法,扩展欧几里得算法,例题。这是你也能看懂的数论。欧几里得算法首先讲一下欧几里得算法欧几里得算法是可以在$O(\log_n)$时间内求解两数最大......
  • 数论分块
    数论分块首先我们需要知道数论分块的用途:它可以快速计算含有除法向下取整的和式。形如\(\sum_{i=1}^{n}f(i)g(\lfloor{\frac{n}{i}}\rfloor)\).为什么可以快速计算呢,因为......
  • SPOJ GCDMAT - GCD OF MATRIX
    简要题意给出三个整数\(T,n,m\),\(T\)组询问,每组询问给出四个整数\(i_1,j_1,i_2,j_2\)(数据保证\(i_1,j_1\leqn\\i_2,j_2\leqm\)),计算:\[\sum_{i=i_1}^{i_2}\sum_{j=......
  • BZOJ 4833 最小公倍佩尔数 题解 (数论,推式子)
    题目链接神奇数论题。做这题需要知道两个结论:对于满足\(f_{i+2}=a\cdotf_{i+1}+b\cdotf_{i}\),也就是形式类似斐波那契数列的序列,有\(gcd(f_i,f_j)=f_{gcd(i,j)}\)(据......
  • SPOJ PGCD - Primes in GCD Table
    简要题意\(T\)组数据,每组数据给出两个整数\(N,M\),求:\[\sum_{i=1}^{N}\sum_{j=1}^{M}{[\gcd(i,j)\in\mathbb{P}]}\]\(1\leqN,M\leq10^7,T\leq10\)思路双倍经验P225......
  • HDU 6273 Master of GCD(差分)
    题目分析贴一个别人的题解这个题就是一个差分数组,因为这数列的最大公约数就是这个数列2的出现2的最少次数的幂乘以3的出现3的最少次数的幂将2和3分开讨论,然后分......
  • 题解——GCD
    给定正整数\(n\),求\(1\lex,y\len\)且\(\gcd(x,y)\)为素数的数对\((x,y)\)有多少对。\(n\le10^7\)题解做法1题意即为求\(S=\sum_{质数p|n}\sum_{i=1}^n\sum_{......
  • 数论分块
    数论分块数论分块也叫整除分块是用于快速处理类似于\[\sum_{i=1}^n\lceil\frac{n}{i}\rceil\text{或者}\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\]式子的一......