• 【题解】P5589 小猪佩奇玩游戏(期望)


    【题解】P5589 小猪佩奇玩游戏(期望)

    假设一个点有(x)个点(包括自己)可以到达他,他就对答案有(1/x)的贡献。这是因为这个点必须被删掉而通过删掉这个点本身删掉这个点的概率是(1/x),所以对期望的贡献是(1 imes 1/x)

    如何算(x)(x)是唯一分解之后所有的指数的(gcd)的约数个数。

    此时就有60分了。

    考虑对于(le sqrt n)的数暴力处理,对于(> sqrt n)的数,由于这些数不会有出度,所以只要算他们的入度。众所周知形如(x^y)的整数是很少的。具体的,大概是:

    [O(sum_{i=1}^{sqrt n} log_i n) ]

    实在是太小了!所以我们定位一个(le sqrt n)的数,然后枚举它所有的幂然后暴力计算即可。但是要去重,具体实现用哈希。

    还有一些出度入度都为(0)的点,直接+1

    复杂度(O( ext{随便过}))

     //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<set>
    #include<unordered_set>
    
    using namespace std;  typedef long long ll;  typedef long double lb;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(!isdigit(c))f|=c==45,c=getchar();
          while(isdigit(c)) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    const int maxn=1e7+5;
    int n,usd[maxn],Min[maxn];
    vector<int> e;
    inline void pre(const int&n){
          usd[1]=1; Min[1]=10;
          for(int t=2;t<=n;++t){
    	    if(!usd[t])e.push_back(t),Min[t]=t;
    	    for(auto i:e){
    		  if(1ll*i*t>n)break;
    		  usd[i*t]=1,Min[i*t]=i;
    		  if(t%i==0)break;
    	    }
          }
    }
    
    int gcd(const int&x,const int&y){return y?gcd(y,x%y):x;}
    inline int getd(int x){
          if(x==1)return 1;
          int d=0;
          while(x>1){
    	    int g=Min[x],cnt=0;
    	    while(x%g==0&&x>1) ++cnt,x/=g;
    	    d=gcd(d,cnt);
          }
          return d;
    }
    int K=0;
    inline lb getsig(int x){
          if(x==1) return 1;
          ll ret=1;
          while(x>1){
    	    K=max(K,x);
    	    int g=Min[x],cnt=0;
    	    while(x%g==0&&x>1) ++cnt,x/=g;
    	    ret=ret*(cnt+1LL);
          }
          return (lb)1/ret;
    }
    
    unordered_set<int> s;
    int main(){
          pre(maxn-1);
          int T=qr();
          while(T--){
    	    int n=qr(),N=sqrt(n);
    	    lb ans=0;
    	    for(int t=1;t<=N;++t) ans+=getsig(getd(t));
    	    ll k=2;
    	    for(int t=2,cnt;t<=N;k=++t){
    		  int d=getd(t);
    		  cnt=1;
    		  while(k<=N) k=k*t,++cnt;
    		  while(k<=n){
    			if(s.find(k)==s.end())
    			      s.insert(k),ans+=getsig(d*cnt);
    			k=k*t,++cnt;
    		  }
    	    }
    	    ans+=(n-N-s.size());
    	    printf("%Lf
    ",ans);
    	    s.clear();
          }
          return 0;
    }
    
    
    
  • 相关阅读:
    我的第一次面试 —— 腾讯 AI安全 一面总结
    从零开始openGL——五、光线追踪
    从零开始openGL——四、纹理贴图与n次B样条曲线
    从零开始openGL——三、模型加载及鼠标交互实现
    从零开始openGL—— 二、 基本图形绘制
    NN入门,手把手教你用Numpy手撕NN(三)
    2020计算机保研经验分享
    TCP实战二(半连接队列、全连接队列)
    TCP实战一(三握四挥、流量控制)
    tcpdump抓包工具的基本使用
  • 原文地址:https://www.cnblogs.com/winlere/p/11666737.html
Copyright © 2020-2023  润新知