数论杂题

首先我们从质因数方面想,任意两个数有公共的质因数,很显然可以成这样:

\[ab \quad bc \quad ac ..... \]

但是 \(n \leq 50\),这样就可能需要高精,并不是很优。

于是我们来想想如何只用几个素数表示出这个序列。

我们知道所有数的 \(gcd\)\(1\) ,不是必须每两个数之间都要为 \(1\) ,只需要有一个 \(1\) 就行。

我们在想想刚才的做法,\(ab \quad bc \quad ac\) 这几个数已经 \(gcd\)\(1\) 了,那么剩下的数只需要互相之间 \(gcd\) 不为 \(1\) 就行了。

所以我们最终可以构造出:

\[ab\quad bc\quad ac\quad 2ac \quad 3ac..... \]

Code

#include<bits/stdc++.h>
using namespace std;
int n;
int a=2,b=3,c=5;
signed main(){
	cin>>n;
	if(n==2){
		cout<<"-1";
		return 0;
	}
	else{
		cout<<a*b<<"\n";
		cout<<a*c<<"\n";
		for(int i=1;i<=n-2;i++){
			cout<<i*b*c<<"\n";
		}
	}
}

给出 \([x,y]\) 求在 \(x_{i-y} \quad x_{i-y+1} \quad ... \quad x_{i-1}\)中有多少个数与 \(x\) \(gcd\) 不为 \(1\)

我们可以去记录下 \(x\) 的每个因子上次出现的位置,若在范围内 \(ans++\) ,并更新。

Code

#include<bits/stdc++.h>
using namespace std;
int T;
int ans;
int x,y;
int pre[200040];
signed main(){
	cin>>T;
	memset(pre,-1,sizeof pre);
	for(int i=1;i<=T;i++){
		cin>>x>>y;
		ans=0;
		for(int j=1;j*j<=x;j++){
			if(x%j==0){
				int k1=j,k2=x/j;
			//	cout<<k1<<" "<<k2<<" "<<x<<endl;
				if(pre[k1]+y<i) ans++;
				if(k1!=k2&&pre[k2]+y<i) ans++;
				pre[k1]=pre[k2]=i;
			}
		}
		cout<<ans<<"\n";
	}
	
}

额,首先预处理出每个数的 \(D(i)\)

然后线段树!

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
int a[3000050];
struct node{
	int l,r,sum,flag;
}z[4000005];
int f[3000050];
int opt,l,r;
inline int rd() {
    int x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x;
}

inline void build(int l,int r,int x){
	z[x].l=l;
	z[x].r=r;
	z[x].flag=0;
	if(l==r){
		z[x].sum=rd();
		if(z[x].sum<=2) z[x].flag=1;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,x*2),build(mid+1,r,x*2+1);
	z[x].sum=z[x*2].sum+z[x*2+1].sum;
	z[x].flag=z[x*2].flag&z[x*2+1].flag;
}

inline void chang(int l,int r,int x){
	if(z[x].flag==1){
		return ;
	}
	if(z[x].l==z[x].r){
		z[x].sum=f[z[x].sum];
		if(z[x].sum<=2) z[x].flag=1;
		return ;
	}
	int mid=z[x].l+z[x].r>>1;
	if(l<=mid){
		chang(l,r,x*2);
	}
	if(r>mid){
		chang(l,r,x*2+1);
	}
	z[x].sum=z[x*2].sum+z[x*2+1].sum;
	z[x].flag=z[x*2].flag&z[x*2+1].flag;
}
inline int query(int l,int r,int x){
	if(z[x].l>=l&&z[x].r<=r){
		return z[x].sum;
	}
	int ans=0;
	int mid=z[x].l+z[x].r>>1;
	if(l<=mid){
		ans+=query(l,r,x*2); 
	}
	if(r>mid){
		ans+=query(l,r,x*2+1);
	}
	return ans;
}
int maxx=1e6;

signed main(){
	n=rd(),m=rd();
	for(int i=1;i<=1e6;i++) {
	//	cout<<i<<endl;
		for(int j=i;j<=1e6;j+=i){
		//	cout<<"j"<<" "<<j<<endl;
			f[j]++;
		}
	}
	

	build(1,n,1);
	while(m--){
		opt=rd(),l=rd(),r=rd();
		if(opt==1){
			chang(l,r,1);
		}
		else{
			printf("%lld\n",query(l,r,1));
		}
	} 
}

[CF1189E]

首先解一下式子:

\[(a_i+a_j)({a_i}^2+{a_j}^2)\equiv k ~mod ~ p \]

可解出:

\[{a_i}^4-k*{a_i}~mod~p\equiv {a_j}^4-k*{a_j}~mod~p \]

然后只需要记录下就行了。

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1000004];
int n,mod,k; 
int p[2000005];
signed main(){
	cin>>n>>mod>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		int q=(a[i]*a[i]%mod*a[i]%mod*a[i]%mod-k*a[i]%mod+mod)%mod;
		p[i]=q;
	}
	sort(p+1,p+1+n);
	int len=0,ans=0;
	for(int i=1;i<=n;i++){
		//cout<<p[i]<<endl;
		if(p[i]==p[i+1]){
			len++;
		}
		else{
			len++;
			//cout<<"len "<<len<<endl;
			ans+=(len-1)*len/2;
			len=0;
		}
	}
	ans+=(len-1)*len/2;
	cout<<ans; 
}
posted @ 2025-05-06 21:37  Distant_Cloud  阅读(21)  评论(0)    收藏  举报