• BZOJ2671: Calc


    BZOJ2671: Calc

    Description

      给出N,统计满足下面条件的数对(a,b)的个数:
      1.1<=a<b<=N
      2.a+b整除a*b

    Input

     一行一个数N

    Output

     一行一个数表示答案

    Sample Input

    15

    Sample Output

    4

    HINT

    数据规模和约定

    Test N Test N 

    1 <=10 11 <=5*10^7 

    2 <=50 12 <=10^8 

    3 <=10^3 13 <=2*10^8 

    4 <=5*10^3 14 <=3*10^8 

    5 <=2*10^4 15 <=5*10^8 

    6 <=2*10^5 16 <=10^9 

    7 <=2*10^6 17 <=10^9 

    8 <=10^7 18 <=2^31-1 

    9 <=2*10^7 19 <=2^31-1 

    10 <=3*10^7 20 <=2^31-1


    题解Here!
    这是一道神题。。。
    所以我不会做。。。
    只能去抄题解。。。
    厚颜无耻写文。。。
    题目要求:$Ans=sum_{i=1}^nsum_{j=1}^n[(i+j)|(ij)]$
    我们把那个$(i+j)|(ij)$单独提出来看。
    这个推导的过程可能比较扯淡复杂。。。
    设$d=gcd(i,j)$,那么原式即为$$d(frac{i}{d}+frac{j}{d})|(frac{ij}{d^2})d^2$$
    消去一个$d$:$$(frac{i}{d}+frac{j}{d})|(frac{ij}{d^2})d$$
    设$u=frac{i}{d},v=frac{j}{d}$,则:$$(u+v)|(uv)d$$
    而我们知道这时$u+v$与$uv$已经没有公约数了,不能再消去了。
    于是变成了:$$(u+v)|d$$
    神奇吧。。。
    我们注意到$(u+v)d<=n,u<=d,v<=d$,所以有:$$u,v in [1,sqrt n]$$
    所以题目就转化为:求$$sum_{u=1}^{sqrt n}sum_{v=1}^{u-1}lfloorfrac{n}{u+v} floor[gcd(u,v)==1]$$
    我们看到了熟悉的东西:$[gcd(u,v)==1]$
    莫比乌斯反演!
    于是:$$sum_{d=1}^{sqrt n}mu(d)sum_{u=1}^{lfloorfrac{sqrt n}{d} floor}sum_{v=1}^{u-1}lfloorfrac{n}{(u+v)d^2} floor$$
    然后就可以愉快地跑了!
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    long long n;
    int k=0,prime[MAXN],mu[MAXN];
    bool np[MAXN];
    inline long long read(){
    	long long date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void make(){
    	int m=MAXN-10;
    	mu[1]=1;
    	for(int i=2;i<=m;i++){
    		if(!np[i]){
    			prime[++k]=i;
    			mu[i]=-1;
    		}
    		for(int j=1;j<=k&&prime[j]*i<=m;j++){
    			np[prime[j]*i]=true;
    			if(i%prime[j]==0)break;
    			mu[prime[j]*i]=-mu[i];
    		}
    	}
    }
    long long calculate(int n,int m){
    	long long s=0;
    	for(int i=1;i<=m;i++){
    		int t=n/i;
    		for(int j=i+1,last;j<(i<<1)&&j<=t;j=last+1){
    			last=min((i<<1)-1,t/(t/j));
    			s+=1LL*(last-j+1)*(t/j);
    		}
    	}
    	return s;
    }
    long long solve(long long n){
    	long long ans=0,m=sqrt(n);
    	for(int i=1;i<=m;i++)ans+=1LL*mu[i]*calculate(n/i/i,m/i);
    	return ans;
    }
    int main(){
    	make();
    	n=read();
    	printf("%lld
    ",solve(n));
        return 0;
    }
    
  • 相关阅读:
    创始人透露Twitter新盈利计划:第三方将受益
    试试ScribeFire转发我的其它博客
    2009年12月30日:新网因清除URL转发域名导致DNS解析故障
    VS2008 如果更改源代码管理插件,将关闭活动解决方案或项目
    Linq使用Group By经验总结
    使用C#的BitmapData
    Java与C#开发上的一些差异与转换方法
    成都七中成绩文件导入SQL脚本
    用SQL SERVER对EXCEL数据进行处理
    NULLIF和ISNULL
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9498519.html
Copyright © 2020-2023  润新知