【福建集训】质数与约数(2.5/3)
A.判断原根
fai(p)=p-1
如果数x%m余1,那么x的n次幂也满足余1,所以我们可以对p-1分解质因数,依次判断每个质因数做质数时是否成立,有一个满足即为成立
#include<bits/stdc++.h> using namespace std; #define re register #define fo1(l,r) for(re int i=l;i<=r;++i) #define fo2(l,r) for(re int j=l;j<=r;++j) #define fo3(l,r) for(re int k=l;k<=r;++k) #define fo4(l,r) for(re int tt=l;tt<=r;++tt) #define fo(l) for(re int i=h[l],go;i;i=x[i].last) #define inf 0x3f3f3f3f #define INF 0x7fffffffffffffff #define LL long long #define itn int #define DB double inline LL read() { LL x=0,f=1;char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { x=(x<<3)+(x<<1)+ch-48; ch=getchar(); } return x*f; } LL a[1000000],cnt; int main() { LL p=read(),n=read(); LL ls=sqrt(p-1); for(re int i=2;i<=(p-1)/i;++i) { if((p-1)%i==0) { a[++cnt]=i; if(i!=(p-1)/i) { a[++cnt]=(p-1)/i; } } } if(cnt==0) { fo1(1,n) { int ls1=read(); printf("YES\n"); } } else { fo1(1,n) { bool pd=0; LL r=read(); fo2(1,cnt) { LL t=a[j],ans=1,base=r%p; while(t) { if(t&1) { ans=ans*base%p; ans%=p; } base=base*base%p; base%=p; t>>=1; } if(ans==1) { pd=1; break; } } if(pd==0) { printf("YES\n"); } else { printf("NO\n"); } } } return 0; }
B.最强辅助
此题模型,就是“一个数n被1~n每个数模的余数之和”的转化,首先先写式子,提出无关的n,将%转化,然后转为积性函数
#include<bits/stdc++.h> using namespace std; #define re register #define fo1(l,r) for(re int i=l;i<=r;++i) #define fo2(l,r) for(re int j=l;j<=r;++j) #define fo3(l,r) for(re int k=l;k<=r;++k) #define fo4(l,r) for(re int tt=l;tt<=r;++tt) #define fo(l) for(re int i=h[l],go;i;i=x[i].last) #define inf 0x3f3f3f3f #define INF 0x7fffffffffffffff #define LL long long #define itn int #define DB double inline LL read() { LL x=0,f=1;char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { x=(x<<3)+(x<<1)+ch-48; ch=getchar(); } return x*f; } const int N=1e7+50,MA=1e6; LL prime[MA],s[N],v[N],a[N],p[N]; int cnt; int main() { freopen("treatment.in","r",stdin); freopen("treatment.out","w",stdout); p[1]=1; s[1]=1; fo1(2,1e7) { if(v[i]==0) { v[i]=i; prime[++cnt]=i; p[i]=i+1; a[i]=i+1; } fo2(1,cnt) { LL ls=1ll*prime[j]*i; if(ls>N-10) break; v[ls]=prime[j]; if(prime[j]==v[i]) { a[ls]=1ll*a[i]*prime[j]+1; p[ls]=1ll*p[i]/a[i]*a[ls]; break; } a[ls]=prime[j]+1; p[ls]=1ll*a[ls]*p[i]; } s[i]=s[i-1]+p[i]; } int t=read(); fo4(1,t) { LL n=read(); LL ANS=1ll*n*n; ANS-=s[n]; printf("%lld\n",ANS); } fclose(stdin); fclose(stdout); return 0; }
C.QQ数题
本题最重要的结论是,一个数的QQ值实际上就是“正约数个数-2^(质因子个数)",但直接求解的复杂度是nlogn级别
这个结论的证明利用了容斥,试想数可以分为2种:①QQ数②非QQ数(废话
而②需要满足的条件只有,每种质因数出现次数要么是1要么是0,所以每种质因数有两种情况,故2^(质因子个数)
进一步优化,利用线性筛降低到O(N),但即便如此还是不行,正解特别麻烦,O(n)只能过一半的数据
#include<bits/stdc++.h> using namespace std; #define re register #define fo1(l,r) for(re int i=l;i<=r;++i) #define fo2(l,r) for(re int j=l;j<=r;++j) #define fo3(l,r) for(re int k=l;k<=r;++k) #define fo4(l,r) for(re int tt=l;tt<=r;++tt) #define fo(l) for(re int i=h[l],go;i;i=x[i].last) #define inf 0x3f3f3f3f #define INF 0x7fffffffffffffff #define LL long long #define itn int #define DB double inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { x=(x<<3)+(x<<1)+ch-48; ch=getchar(); } return x*f; } const int N=1e7+50,MA=1e6+10; LL v[N],prime[MA],a[N],s[N],b[N],c[N]; LL ss[30]; itn cnt; int main() { freopen("number.in","r",stdin); freopen("number.out","w",stdout); ss[0]=1; fo1(1,29) ss[i]=1ll*ss[i-1]*2; s[1]=0; fo1(2,1e7) { if(v[i]==0) { v[i]=i; a[i]=2; b[i]=1; c[i]=1; prime[++cnt]=i; } fo2(1,cnt) { LL ls=1ll*i*prime[j]; if(ls>N-30) break; v[ls]=prime[j]; if(prime[j]==v[i]) { a[ls]=1ll*a[i]/(b[i]+1)*1ll*(b[i]+2); b[ls]=b[i]+1; c[ls]=c[i]; break; } c[ls]=c[i]+1; a[ls]=1ll*a[i]*2; b[ls]=1; } s[i]=s[i-1]+a[i]-ss[c[i]]; // cout<<i<<" "<<a[i]<<endl; } itn l=read(),r=read(); LL ANS=s[r]-s[l-1]; printf("%lld",ANS); fclose(stdin); fclose(stdout); return 0; }

浙公网安备 33010602011771号