【福建集训】质数与约数(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;
}

 

posted @ 2023-07-24 17:03  小鱼儿吼吼  阅读(14)  评论(0)    收藏  举报