• 【题解】SP34096 DIVCNTK


    题目大意:求 (sum_{i=1}^n ho(i^k))

    观察一下它的性质:(下面简记 (p) 为质数)

    • (f(p)= ho(p^k)=k+1)

    • (f(p^alpha)= ho(p^{alpha k} )=alpha k+1)

    • (f(ab)= ho((ab)^k)= ho(a^k) ho(b^k)=f(a)f(b)[gcd(a,b)=1])

    于是它满足:是积性函数,在 (p,p^k) 的值可以快速计算。

    于是就可以用 Min_25 筛了,复杂度是 (O(frac{n^{frac{3}{4}}}{log n}))

    这篇题解没有讲关于 Min_25 的具体实现,主要是想要说一下做的时候遇到的问题:

    求 Min_25 中 (g) 数组的过程中是需要把 (f(x)) 拆解成一些完全积性函数的,这个时候我把 (f(p)=k+1) 拆成了 (f_0(p)=1,f_1(p)=k) 两个函数,乍一看没什么问题,但仔细想想会发现:

    ([gcd(a,b)=1]f(ab)=f(a)f(b)=k^2 ot =k)

    所以这个 (f_1) 并不是积性函数!

    以后拆的时候一定要注意,不能看着像就写上了,要不然调好久都不知道为啥。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int unsigned long long
    typedef unsigned long long ull;
    const int N=2e5+10;
    namespace Min_25{
    	ull T,g1[N],w[N];
    	ull sp,n,k,id1[N],id2[N];
    	int sq,cnt,m,p[N],sum1[N];
    	bool vis[N];
    	void pre(){
    		for(int i=2;i<=sq;++i){
    			if(!vis[i])p[++cnt]=i;
    			for(int j=1;j<=cnt&&i*p[j]<=sq;++j){
    				vis[i*p[j]]=1;
    				if(i%p[j]==0)break;
    			}
    		}
    		for(int i=1;i<=cnt;++i)sum1[i]=sum1[i-1]+1;
    	}
    	inline ull f1(ull x){return x;}
    	inline ull getid(ull x){if(x<=sq)return id1[x];return id2[n/x];}
    	ull S(ull x,int j){
    		if(p[j]>x)return 0;
    		ull Ans=(g1[getid(x)])-(sum1[j]+sum1[j]*k);
    		for(int i=j+1;i<=cnt&&p[i]*p[i]<=x;++i){
    			for(int e=1,sp=p[i];sp<=x;sp*=p[i],++e){
    				Ans+=(k*e+1)*(S(x/sp,i)+(e>1));
    			}
    		}
    		return Ans;
    	}
    	inline void write(ull x){
    		if(x>9)write(x/10);
    		putchar(x%10+'0');
    	}
    	void solve(){
    		cin>>T;
    		sq=100000;
    		pre();
    		while(T--){
    			cin>>n>>k;
    			for(ull l=1,r;l<=n;l=r+1){
    				ull d=n/l;
    				w[++m]=d;r=n/d;
    				g1[m]=f1(w[m])-1;
    				if(w[m]<=sq)id1[w[m]]=m;
    				else id2[r]=m;
    			} 
    			for(int i=1;i<=cnt;++i)
    				for(int j=1;j<=m&&p[i]*p[i]<=w[j];++j){
    					g1[j]=g1[j]-(g1[getid(w[j]/p[i])]-sum1[i-1]);
    				}
    			for(int j=1;j<=m;++j)g1[j]=g1[j]*(k+1);
    			write(S(n,0)+1);putchar('
    ');
    			for(int i=1;i<=m;++i)id1[w[m]]=id2[w[m]]=0,g1[i]=w[i]=0;
    			m=0;
    		}
    	}
    }
    signed main(){
    	Min_25::solve();
    	return 0;
    } 
    
  • 相关阅读:
    Tcp抓包以及Tcp状态
    Wireshark抓包使用指南
    服务端tcp syn无响应,无回复
    升级openssh
    平滑升级Nginx
    Memcached 未授权访问漏洞修复
    服务端高并发分布式架构演进之路
    es索引查询与删除
    申请elasticsearch中x-pack插件许可证及授权
    独立安装ab压力测试工具及测试nginx性能
  • 原文地址:https://www.cnblogs.com/h-lka/p/15085107.html
Copyright © 2020-2023  润新知