数论杂题
首先我们从质因数方面想,任意两个数有公共的质因数,很显然可以成这样:
\[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;
}