• bzoj 3481 DZY Loves Math III——反演+rho分解质因数


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3481

    推推式子发现:令Q=gcd(P,Q),ans=Σ(d|Q) d*phi(P/d)。把 d 质因数分解,设 t 为 Q 的指数, w 为 P 的指数,ans变成每个质数的 Σ(i=0~t) p^i * phi( p^(w-i) ) 连乘。

    分解质因数用 Pollar Rho 。

    注意 Q=0 就是 Q=P,要特判!而且不要以为答案变成  (!x || !y) 了!

    d从0到P-1 就是 d从1到P!不要特判 P==Q时给答案减P !因为算的时候就没算d=0的!

    每个质数的那个式子可以化简,把 phi 写开,和 p^i 合并,就不用枚举 i 。但要注意 w-i ==0 时 phi 的式子有些不同了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #define ll long long
    using namespace std;
    const int N=650,mod=1e9+7;
    int n,ans=1,c[N],c2[N],tot;
    ll p[N],P=1;
    bool vis[N],flag;
    ll rdl()
    {
      ll ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3ll)+(ret<<1ll)+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    void upd(ll &x,ll md){x-=(x>=md?md:0);}
    ll mul(ll a,ll b,ll md)
    {
      ll ret=0;//0!
      while(b)
        {
          if(b&1ll)ret=ret+a,upd(ret,md);
          a=a+a,upd(a,md);b>>=1ll;
        }
      return ret;
    }
    ll pw(ll x,ll k,ll md)
    {
      ll ret=1;
      while(k)
        {
          if(k&1ll)ret=mul(ret,x,md);
          x=mul(x,x,md);k>>=1ll;
        }
      return ret;
    }
    int phi(ll p,int k)
    {
      if(!k) return 1;
      return mul(p-1,pw(p,k-1,mod),mod);
    }
    void add(ll a,bool flag)
    {
      if(flag)
        {
          for(int i=1;i<=tot;i++)
        if(p[i]==a)
          { c[i]++;return;}
          p[++tot]=a; c[tot]=1;
        }
      else
        {
          for(int i=1;i<=tot;i++)
        if(p[i]==a&&c2[i]<c[i])
          c2[i]++;//Q=gcd()
        }
    }
    bool ml_rb(ll n)
    {
      if(n<2)return false;if(n==2)return true;if((n&1)==0)return false;
      ll u=n-1,t=0;
      while((u&1)==0){u>>=1,t++;}
      int s=20;
      while(s--)
        {
          ll a=rand()%(n-2)+2;//2~n-1
          a=pw(a,u,n); ll pre=a;
          for(int i=1;i<=t;i++)
        {
          a=mul(a,a,n);
          if(a==1&&pre!=1&&pre!=n-1)return false;
          pre=a;
        }
          if(a!=1) return false;
        }
      return true;
    }
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll pl_rho(ll x,ll c)
    {
      ll x0=rand()%x,y0=x, k=1,i=0;
      while(1)
        {
          x0=(mul(x0,x0,x)+c)%x;
          ll g=gcd(abs(x0-y0),x);
          if(g!=1&&g!=x) return g;
          if(x0==y0)return x;
          if((++i)==k){k<<=1;y0=x0;}
        }
    }
    void fd_fac(ll n,bool flag)
    {
      if(n<2)return;
      if(ml_rb(n))
        {
          add(n,flag);return;
        }
      ll p=n;
      while(p==n)p=pl_rho(p,rand()%(n-1)+1);
      fd_fac(p,flag); fd_fac(n/p,flag);
    }
    int main()
    {
      srand(time(0));  n=rdl();
      for(int i=1;i<=n;i++)
        {
          ll a=rdl(); P=mul(P,a,mod);
          fd_fac(a,1);
        }
      for(int i=1;i<=n;i++)
        {
          ll a=rdl(); if(!a){flag=1;continue;}
          if(flag)continue;
          fd_fac(a,0);
        }
      if(flag)for(int i=1;i<=tot;i++)c2[i]=c[i];
      for(int i=1,d,tp;i<=tot;i++)
        {
          tp=pw(p[i],c[i]-1,mod);
          d=mul(tp,mul(p[i]-1,c2[i]+1,mod)+(c[i]==c2[i]),mod);
          ans=mul(ans,d,mod);
        }
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    Spring Boot Admin 添加报警提醒和登录验证功能!
    安卓平板体验Java开发,还能白嫖一年阿里无影云,真香!
    Java中停止线程的3种方式
    Nacos中服务删除不了,怎么办?
    面试突击30:线程池是如何执行的?拒绝策略有哪些?
    面试突击25:sleep和wait有什么区别
    SpringCloud Nacos + Ribbon 调用服务的 2 种方法!
    为什么start方法不能重复调用?而run方法却可以?
    Spring Cloud Alibaba Nacos 服务注册与发现功能实现!
    多图|一文详解Nacos参数!
  • 原文地址:https://www.cnblogs.com/Narh/p/9753293.html
Copyright © 2020-2023  润新知