• [牛客Wannafly挑战赛27D]绿魔*


    description

    newcoder
    给你一个空的可重集合(S)
    (n)次操作,每次操作给出(x),(k),(p),执行以下操作:
    (opt 1):在S中加入x。
    (opt 2):输出

    [sum_{yin S}gcd(x,y)^k ]

    data range

    所有输入的数都是小于(10^5+1)的正整数。

    solution

    考场降智系列

    对于一个(x),其(gcd(x,y))(O(d(x))le O(sqrt x))
    这里(d(x))(x)的约数个数

    枚举(x)的约数(d),考虑如何算出(gcd(x,y)==d)(y)的个数
    我们可以(O(nsqrt x))地动态维护集合(S)(i)的倍数的数的个数(p[i])

    但是(d)的倍数和(x)(gcd)显然不一定是(d)

    这里有一个可能比较简单的容斥做法:
    考虑一开始(gcd(x,y)==x)的数的个数肯定是(=p[x])的。
    于是可以在(p[i<x])中减掉(p[x]).
    之后(x)的次大的约数也会变成正确答案;
    这样逐级做下去即可求出我们需要的答案。

    复杂度?
    看起来是(O(nsqrt nsqrt{sqrt n})=O(n^{frac{7}{4}}))的...
    但是(=O(能过))

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define Cpy(x,y) memcpy(x,y,sizeof(x))
    #define Set(x,y) memset(x,y,sizeof(x))
    #define FILE "a"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ll;
    typedef vector<int>VI;
    //typedef long long ll;
    typedef double dd;
    const int N=2e5+10;
    const int M=5e4+10;
    const int mod=998244353;
    const int base=113;
    const dd eps=1e-8;
    const int inf=1e9;
    const ll INF=1ll<<60;
    const ll P=100000;
    #define mod (10007)
    il int read(){
      RG int data=0,w=1;RG char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
      if(ch=='-')w=-1,ch=getchar();
      while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
      return data*w;
    }
    il void file(){
      srand(time(NULL)+rand());
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
    }
    
    inline int poww(int a,int b,int p){
      RG int ret=1;
      for(;b;b>>=1,a=1ll*a*a%p)
        if(b&1)ret=1ll*ret*a%p;
      return ret;
    }
    
    int n,cnt[N],pw[N],cal[N],top,f[N];VI fac[N];
    inline void sieve(){
      for(RG int i=1;i<=100000;i++)
        for(RG int j=i;j<=100000;j+=i)
          fac[j].push_back(i);
    }
    
    int main()
    {
      sieve();n=read();
      for(RG int i=1,x,k,p,tmp,res,sz;i<=n;i++){
        x=read();k=read();p=read();top=res=0;
        sz=fac[x].size();
        for(RG int j=0;j<sz;j++){
          cnt[fac[x][j]]++;f[fac[x][j]]=cnt[fac[x][j]];
        }
        for(RG int j=sz-1;~j;j--)
          for(RG int siz=fac[fac[x][j]].size(),k=siz-1;~k;k--)
    	if(fac[x][j]!=1&&fac[x][j]!=fac[fac[x][j]][k])
    	  f[fac[fac[x][j]][k]]-=f[fac[x][j]];
        for(RG int j=0;j<sz;j++)
          {res+=1ll*f[fac[x][j]]*poww(fac[x][j],k,p)%p;if(res>=p)res-=p;}
        printf("%d
    ",res);
      }
      return 0;
    }
    
    
  • 相关阅读:
    ACM-超级楼梯
    clientt.c
    call.c
    answer.c
    aa.c
    client.c
    service.c
    自己动手开发jQuery插件
    apache-commons-net Ftp 进行文件、文件夹的上传下载及日志的输出
    在Eclipse中制作SSH配置文件提示插件
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9859161.html
Copyright © 2020-2023  润新知