【与因数有关的问题】

【与因数有关的问题】

d(m):表示m的因数
可用于求复杂度:比O(logn)小
求因数可避免遍历整个n->优化点

Modular Sorting

https://codeforces.com/contest/2123/problem/G

题目大意

image

思路

【思路】
设d=gcd(k,m) 那么d应该都是m的因数->可以预处理所有的因数
对于一个数列A (a[i]+k*cnt)%m都是d的倍数

容易想到O(nq)做法:判断下一个数能不能比上一个数大

优化:(常见思路)插入操作同步处理 使得查询为O(1)
->考虑在d的情况下 需要+多少次->最多操作m/d-1次 超过了肯定不满足
->当a[i]%d>a[i+1]%d时需要操作

->对于每一个修改操作:只会改变a[i-1],a[i]和a[i+1],a[i]的关系
->查询操作:查cnt[d]即可

image

代码

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define whiteink signed main
#define fi first
#define sc second

using i64=long long;
using i128=__int128;
typedef pair<int,int> PII;
typedef pair<i64,i64> P64;
i64 max64(i64 a,i64 b){return a>b?a:b;}
i64 min64(i64 a,i64 b){return a<b?a:b;}
bool cmp(int a,int b){return a>b;}
bool cmp64(i64 a,i64 b){return a>b;}

const int inf_int=0x3f3f3f3f;
const i64 inf_i64=0x3f3f3f3f3f3f3f3f;
const i64 mod=1e9+7;

//快速幂
i64 qmi(i64 a,i64 k,i64 p){
	i64 res=1LL;
	while(k){
		if(k&1LL) res=res*a%p;
		k>>=1LL;//删去k的末位 
		a=a*a%p;
	}
	return res;
}

//gcd
i64 gcd(i64 a,i64 b){
	return b?gcd(b,a%b):a;
}

//求约数
vector<int> get_divisors(int qaq){
	vector<int> res;
	for(int i=1;i<=qaq/i;i++){
		if(qaq%i==0){
			res.push_back(i);
			if(i!=qaq/i) res.push_back(qaq/i);
		}
	}
	sort(res.begin(),res.end());
	return res;
}

const int N=3e5+10;
int n,m,q;
vector<vector<int>> fac;
//找所有因数
void init(int x){
	fac.resize(x+1);
	for(int i=1;i<=x;i++){
		for(int j=i;j<=x;j+=i){
			fac[j].push_back(i);
		}
	}
}
void solve(){
    cin>>n>>m>>q;
	vector<int> a(n+1,0);
	int k=fac[m].size();
	map<int,int> cnt;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<n;i++){
		for(auto d:fac[m]){
			if(a[i]%d>a[i+1]%d) cnt[d]+=1;
		}
	}
	while(q--){
		int op;
		cin>>op;
		if(op==1){
			int i,x;
			cin>>i>>x;
			if(i>1){
				for(auto d:fac[m]){
					if(a[i-1]%d>a[i]%d) cnt[d]-=1;
				}
				for(auto d:fac[m]){
					if(a[i-1]%d>x%d) cnt[d]+=1;
				}
			}
			if(i<n){
				for(auto d:fac[m]){
					if(a[i]%d>a[i+1]%d) cnt[d]-=1;
				}
				for(auto d:fac[m]){
					if(x%d>a[i+1]%d) cnt[d]+=1;
				}
			}
			a[i]=x;
		}
		else if(op==2){
			int kk;
			cin>>kk;
			int d=gcd(kk,m);
			if(cnt[d]>m/d-1){
				cout<<"NO"<<endl;
			}
			else{
				cout<<"YES"<<endl;
			}
		}
	}
}

whiteink(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	init(5e5);
    //precompute();

    int T=1;
    cin>>T;
    while(T--) solve();
    return 0;
}
posted @ 2025-07-05 15:26  White_ink  阅读(12)  评论(0)    收藏  举报