首页 > 其他分享 >题解 HDU5726【GCD】/ LGT353762【Soso 的最大公约数】

题解 HDU5726【GCD】/ LGT353762【Soso 的最大公约数】

时间:2023-07-16 20:11:55浏览次数:39  
标签:now GCD int 题解 leq HDU5726 include ds gcd

Problem

给你一个长为 \(N(1\leq N \leq 1\times 10^5)\) 的整数序列:\(a_{1},\cdots,a_{n}(0 <a_{i} \leq 1\times 10^9)\)。

有 \(Q (1\leq Q \leq 1\times 10^5)\) 次提问。每次提问有个范围 \(l, r\),你需要计算出 \(\gcd(a_{l},,a_{l+1},...,a_{r})\) ,并且统计数对 \((l’, r’) \boxed{{(1 \leq l' < r' \leq N)}}\) 的数量。数对满足 \(\gcd(a_{l’},a_{l’+1},...,a_{r’})\) 等于 \(\gcd(a_{l},a_{l+1},...,a_{r})\).

(\(l'=r'\) 似乎是可以的,不知道什么鬼)

Solution

考虑第一问。非常简单,线段树或者 ST 表,因为 \(\gcd\) 有结合律,又有 \(\gcd(x,x)=x\)。

考虑第二问,这一问显然可以暴力预处理答案,但是怎么暴力。考虑枚举右端点,动态维护一个左端点的队列表示可能的 \(\gcd\),那么我们每次放入 \(a_r\),然后把队列中的每个数和 \(a_r\) 取个 \(\gcd\)。这样我们就知道了这个序列的所有 \(\gcd\),形式化一点可以是这样:

\[S_i=\{a_i\}\cup\{\gcd(x,a_i)|x\in S_{i-1}\}. \]

但是为什么它对啊,考虑分析一下 \(S_i\),我们发现随着数字一个个被加进去(固定 \(r\) 向左移动 \(l\)),\(\gcd\) 要么不变要么至少除以二,所以最多被除 \(\log\) 次,所以 \(S_i\) 在去重后的大小不超过 \(\log V\)。

这样的方法也可以查询区间 \(\gcd\),暴力遍历 \(S_r\),根据定义找到答案。写的时候建议倒着。

Solution'

但是有些同学读题不认真,读成 统计数对 \((l’, r’) \boxed{{(l \leq l' \leq r' \leq r)}}\),非常悲伤,但还能做。首先离线询问。

枚举要找的 \(d\),变成询问区间 \([L,R]\) 中有多少个区间的 \(\gcd=d\),非常简单,我们扫描线,大概就是对于形如 \((l,[r])\) 的 pair(表示 \([l,r'\in[r]]\) 的 \(\gcd=d\)),只保留所有 \(l\geq L\) 的,将所有 \([r]\) 的位置加一,然后查询 \([L,R]\) 的和就是了。那么这非常的正确。\(O(n\log^2 n)\)。

Code

原题
#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr,##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
typedef pair<int,int> pii;
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
int n,Q,a[1<<17];
map<int,LL> buc;
vector<pii> d[1<<17];
int mian(){
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=n;i>=1;i--){
		d[i].push_back(pii{i,a[i]});
		if(i<n) for(pii e:d[i+1]){
			pii t={e.first,gcd(e.second,a[i])};
			if(t.second==d[i].back().second) d[i].back().first=t.first;
			else d[i].push_back(t);
		}
		int last=i-1;
		for(pii e:d[i]) buc[e.second]+=e.first-last,last=e.first;
	}
	scanf("%d",&Q);
	for(int l,r;Q--;){
		scanf("%d%d",&l,&r);
		for(pii e:d[l]) if(r<=e.first){
			printf("%d %lld\n",e.second,buc[e.second]);
			break;
		}
	}
	return 0;
}
void reset(){
	static int cnt=0; printf("Case #%d:\n",++cnt);
	buc=map<int,LL>();
	for(int i=1;i<=n;i++) d[i].clear();
}
int main(){
//	#ifdef LOCAL
//	 	freopen("input.in","r",stdin);
//	#endif
	for(scanf("%*d");~scanf("%d",&n);reset(),mian());
	return 0;
}

加强
#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr,##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
typedef pair<int,int> pii;
template<int N,class T=int> struct fenwick{
	T t[N+10];
	fenwick(){memset(t,0,sizeof t);}
	void add(T k,int p){for(;p<=N;p+=p&-p) t[p]+=k;}
	T query(int p){T res=0;for(;p>=1;p-=p&-p) res+=t[p];return res;}
};
template<int N,class T=int> struct segtree{//exfenwick
	fenwick<N,T> s,t;
	void add(T k,int l,int r){s.add(k,l),s.add(-k,r+1),t.add(k*(l-1),l),t.add(-k*r,r+1);}
	T query(int p){return s.query(p)*p-t.query(p);}
	T query(int l,int r){return query(r)-query(l-1);}
};
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
int n,Q,a[1<<17],Lq[1<<17],Rq[1<<17];
map<int,vector<int>> ids;
map<int,vector<tuple<int,int,int>>> idd;
vector<pii> d[1<<17];
LL ans[1<<17];
segtree<1<<17,LL> t;
int solve(int l,int r){
	for(pii e:d[l]) if(r<=e.first) return e.second;
	assert(0); return -1;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=n;i>=1;i--){
		d[i].push_back(pii{i,a[i]});
		if(i<n) for(auto&&e:d[i+1]){
			pii t={e.first,gcd(e.second,a[i])};
			if(t.second==d[i].back().second) d[i].back().first=t.first;
			else d[i].push_back(t);
		}
		int last=i-1;
		for(auto&&e:d[i]) idd[e.second].emplace_back(i,last+1,e.first),last=e.first;
	}
	scanf("%d",&Q);
	for(int i=1;i<=Q;i++) scanf("%d%d",&Lq[i],&Rq[i]),ids[solve(Lq[i],Rq[i])].push_back(i);
	for(auto&&elem:ids){
		int d=elem.first;
		vector<int>&&id=move(elem.second);
		auto&&ds=move(idd[d]);
		for(auto&&rng:ds) t.add(1,get<1>(rng),get<2>(rng));
		int now=(int)ds.size()-1;
		sort(id.begin(),id.end(),[&](int i,int j){return Lq[i]<Lq[j];});
		for(int i:id){
			while(now>=0&&get<0>(ds[now])<Lq[i]) t.add(-1,get<1>(ds[now]),get<2>(ds[now])),now--;
			ans[i]=t.query(Lq[i],Rq[i]);
		}
		while(now>=0) t.add(-1,get<1>(ds[now]),get<2>(ds[now])),now--;
	}
	for(int i=1;i<=Q;i++) printf("%d %d\n",solve(Lq[i],Rq[i]),ans[i]);
	return 0;
}


标签:now,GCD,int,题解,leq,HDU5726,include,ds,gcd
From: https://www.cnblogs.com/caijianhong/p/solution-HDU5726.html

相关文章

  • Codeforces Round 896 Div2 A-D题解
    CodeforcesRound896A.Politics这题问的是,给一些人的在n个议题的观点,然后你可以随意安排顺序,每个议题人多的赢,反对派会离开,问随便安排议题,最多留下多少人,包括我自己这个题刚开始愣了半天,但是想到,那只要把所有和我观点一致的给留下来不就行了???然后交上去就AC了ACCode#inclu......
  • 题解 CF1842H【Tenzing and Random Real Numbers】
    看了题解。好难受,想用积分求概率,算了半天。发现没啥规律,不是不能算,就是太可怕了。Problem有\(n\)个\([0,1]\)范围内的均匀随机变量\(x_{1\cdotsn}\)和\(m\)条限制,每条限制形如\(x_i+x_j\le1\)或\(x_i+x_j\ge1\)。请你求出所有限制均满足的概率。对\(998244353\)......
  • Noip优质模拟赛口胡题解
    HDU5719题意概括:第一行输入t表示输入数据,每组数据第一行n,表示对1—n进行排序。接下来输入n个数b[n]表示排列中第i个数之前的最小值为b[i]。第三行n个数c[n],表示排列中第i个数之前的最大值为c[i]。解题思路:递推,排除掉6种不可能的情况,1、b[i]>b[i-1]2、c[i]<c[i-1]3、b[i]......
  • 2023.07.16 高质量 NOIP 模拟赛题解
    HDU5719Arrange【模拟】给定数列\(B_n,C_n\),求出满足\[B_i=\min_{j=1}^i\{A_j\},\quadC_i=\max_{j=1}^i\{A_j\}\]的排列\(A\)的数量。维护每个位置可能的数字数量,然后乘法原理即可。代码:http://acm.hdu.edu.cn/viewcode.php?rid=38654445。HDU5807KeepInTouch......
  • HHHOJ #1247. 「NOIP 2023 模拟赛 20230715 A」1 题解--zhengjun
    法老找来的题,说是找了三道其他模拟赛的T4拼成T1~T3,另外搞了道T4。思维好题,但是放在T1有点搞心态,但是还好大样例够强,400没挂。然而T3大样例输出错了,浪费了我0.5h,差评。首先发现向左走之后向右走是一定不优的,所以最短路的情况只能先向右再向左。考虑枚举起点\(s......
  • 题解 P2839【[国家集训队] middle】
    Problem一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b_{n/2}\),其中\(a,b\)从\(0\)开始标号,除法下取整。给你一个长度为\(n\)的序列\(s\)。回答\(Q\)个这样的询问:\(s\)的左端点在\([a,b]\)之间,右端点在\([c,d]\)之间的子区间中,最大的中......
  • 你省(福建)省队集训 Day5 T1 题解
    简要题意有两个正整数\(a<b\le10^9\),给出\(\dfrac{a}{b}\)的小数点后\(19\)位,要求还原\(a,b\),保证有解。solution一个科技:\(\texttt{Stern-Brocottree}(SBT)\),可以参考这个博客学习。先给出\(O(n)\)找的代码:......
  • 云斗杯 T2 派蒙是最好的伙伴! 题解
    云斗杯T2题解赛时脑抽了只打了60pts暴力xwx。题目描述给定两个长度为\(n\)的\(01\)序列\({a_n}\)和\({b_n}\),与另一个矩阵\({c_{n,n}}\)。矩阵\({c_{n,n}}\)的生成规则如下:\[c_{i,j}=a_i\timesb_j\]现给定一个数\(k\),求在矩阵\(c_{n,n}\)内,有多少个......
  • freee Programming Contest 2023(AtCoder Beginner Contest 310)题解
    点我看题A-OrderSomethingElse直接比较\(P\)和\(Q+min(D_i)\),输出较小值即可。点击查看代码#include<bits/stdc++.h>#definerep(i,n)for(inti=0;i<n;++i)#definerepn(i,n)for(inti=1;i<=n;++i)#defineLLlonglong#definefifirst#definesesecond#defi......
  • AJAX请求,响应头有set-cookie但浏览器不能写入cookie问题解决!
    开幕雷击:AJAX就不是干这个ajax只有向服务器发送请求时带上cookie的功能可选。不存在ajax向服务器get的时候带回来cookie的功能。解决把AJAX代码改成原始的js代码来完成需求:正确的jsdocument.addEventListener('DOMContentLoaded',function(){document.querySelector('......