zoukankan      html  css  js  c++  java
  • 4.10 省选模拟赛 约数 数论 转换 三元组个数

    avatar
    avatar

    题目很简明 可是 上午反演的时候无计可施。

    直接做是nln的 可以简单转换一下 原式=(sum_{x=1}^nfrac{n}{x}d(x))

    这样就有一个O(n)的做法了 由于d是积性函数直接筛就好了。没必要整除分块 直接O(n).

    const int MAXN=15000010;
    int n,top;
    int v[MAXN],g[MAXN],p[1000010],d[MAXN];
    inline void prepare()
    {
    	d[1]=1;
    	rep(2,n,i)
    	{
    		if(!v[i])
    		{
    			p[++top]=g[i]=v[i]=i;
    			ll sum=p[top];int j=1;
    			while(sum<=n)d[sum]=j+1,sum=sum*p[top],++j;
    		}
    		rep(1,top,j)
    		{
    			if(n/i<p[j])break;
    			int ww=i*p[j];
    			v[ww]=p[j];
    			if(p[j]==v[i])
    			{
    				g[ww]=g[i]*p[j];
    				d[ww]=d[i/g[i]]*d[g[ww]];
    				break;
    			}
    			d[ww]=d[i]*d[p[j]];
    			g[ww]=p[j];
    		}
    	}
    }
    int main()
    {
    	//freopen("divisor.in","r",stdin);
    	//freopen("divisor.out","w",stdout);
    	get(n);
    	if(n<=15000000)
    	{
    		prepare();//put(top);
    		//rep(1,n,i)put(d[i]);
    		ll sum=0;
    		rep(1,n,i)sum=sum+(ll)(n/i)*d[i];
    		putl(sum);
    	}
    	return 0;
    }
    

    推到这里就可以自闭了。

    d这个函数的前缀和不能杜教筛 也没有一个gcd的东西可以代替 如(d(i)=sum_{x=1}^{i}[(x,i)=x])这个东西没啥用 还是很难化简。

    还要一个 (d(xy)=sum_{i|x}^{x}sum_{j|y}^{y}[(i,j)=1])

    都跟本题没啥关系。

    这道题之所以能做是因为 求的是前缀和这个特异性问题。

    (d(w)=sum_{x|w}1) 观察这个东西可以发现(x,frac{w}{x})这个东西是一个二元组。

    (sum_{i=1}^nsum_{p|i}d(p))观察这个东西 对于一个i来说 有(frac{i}{p},d(p))(frac{i}{p},frac{w}{x},x)

    这个三元组会对答案贡献1.

    可以发现 对于所有的三元组 xyz<=n 这样的三元组都会被计数。

    且这个三元组是唯一存在于一个数字i内的。

    设x<=y<=z.若x<=(n^{frac{1}{3}},yleq sqrt(frac{n}{x}))

    枚举x,y统计z的数量即可。

    由于x,y,z可以是一个排列所以要乘6.

    但是观察上面的三元组的情况 发现对于x==y的时候这种情况是没有排列的所以需要减掉相应的次数 三个数字相等也同理。

    非常妙的一道题。至于复杂度接近于(n^{frac{2}{3}})(我也不会证明。

    const ll MAXN=100010;
    ll n;
    int main()
    {
    	freopen("divisor.in","r",stdin);
    	freopen("divisor.out","w",stdout);
    	get(n);
    	ll w1=1,w2=1,ans=0;
    	while(w1*w1*w1<=n)++w1;--w1;
    	while(pf(w2)<=n)++w2;--w2;
    	for(ll i=1;i<=w1;++i)
    	{
    		ll ww=n/i;
    		for(ll j=i;j*j<=ww;++j)ans+=ww/j-j+1;
    	}
    	ll cnt=0;
    	for(ll i=1;i<=w2;++i)cnt+=n/i/i;
    	putl(ans*6-cnt*3-2*w1);
    	return 0;
    }
    
  • 相关阅读:
    MyEclipse WebSphere开发教程:WebSphere 7安装指南(四)
    【DevExpress v17.2新功能预告】增强ASP.NET TreeList
    MyEclipse WebSphere开发教程:WebSphere 7安装指南(三)
    【DevExpress v17.2新功能预告】增强ASP.NET GridView的功能
    MyEclipse WebSphere开发教程:WebSphere 7安装指南(二)
    css如何设置首行文字缩进?
    css可以修改超链接颜色吗?
    css如何将图片横向平铺?
    CSS三种布局模型是什么?
    css怎么样设置透明度?
  • 原文地址:https://www.cnblogs.com/chdy/p/12675665.html
Copyright © 2011-2022 走看看