zoukankan      html  css  js  c++  java
  • [bzoj2820] YY的GCD

    Description

    神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种

    傻×必然不会了,于是向你来请教……多组输入

    Input

    第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M

    Output

    T行,每行一个整数表示第i组数据的结果

    Sample Input

    2
    10 10
    100 100
    

    Sample Output

    30
    2791
    

    HINT

    T = 10000

    N, M <= 10000000

    Source

    题解

    前置知识:莫比乌斯反演

    题目让我们求这个:

    [ans=sum_{i=1}^nsum_{j=1}^m [gcd(i,j) in pri]\ ]

    其中(pri)表示质数集合。

    然后枚举这个质数:

    [egin {align} ans&= sum _{din pri} sum _{i=1}^{n} sum _{j=1}^{m} [gcd(i,j)=d]\ &=sum _{din pri} sum _{i=1}^{lfloor frac{n}{d} floor} sum _{j=1}^{lfloor frac{m}{d} floor} [gcd(i,j)=1] \ end {align} ]

    根据莫比乌斯函数的性质可以得到:

    [sum _{d ^prime|n} mu(d ^prime)=[n=1] ]

    然后把(n)换成(gcd(i,j))带进去,得:

    [ans=sum _{din pri} sum _{i=1}^{lfloor frac{n}{d} floor} sum _{j=1}^{lfloor frac{m}{d} floor} sum _{d^prime|i &d^prime|j} mu (d^prime) ]

    然后先枚举(d^prime),得:

    [egin{align} ans&=sum _{din pri} sum _{d^prime} mu (d^prime) sum _{i=1}^{lfloor frac{n}{dd^prime} floor} sum _{j=1}^{lfloor frac{m}{dd^prime} floor} 1\ ans&= sum _{din pri} sum _{d^prime} mu(d^prime) lfloor frac{n}{dd^prime} floor lfloorfrac{m}{dd^prime} floor end {align} ]

    (T=dd^prime),得:

    [egin{align} ans&= sum _{d in pri } sum _{T}mu(frac{T}{d}) lfloor frac{n}{T} floor lfloorfrac{m}{T} floor \ &= sum _{T}lfloor frac{n}{T} floor lfloorfrac{m}{T} floor sum _{d in pri & d|T} mu(frac{T}{d}) end {align} ]

    [egin {align} & ext{令}f(n) = sum _{din pri & d|T} mu (d) \ &ans= sum _{T}lfloor frac{n}{T} floor lfloorfrac{m}{T} floor f(T) end {align} ]

    线筛出质数和(mu)函数之后,暴力预处理(f)并求出前缀和,然后数论分块就行了。

    由于n以内的质数只有(O(n/ln(n)))个,所以预处理复杂度为(O(n/ln(n)*ln(n/ln(n))+n)=O(n)),具体参考调和级数。

    然后询问的复杂度为(O(qsqrt{n}))

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
    	if(x<0) putchar('-'),x=-x;
    	if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e7+1;
    
    int mu[maxn+10],sum[maxn+10],pri[maxn+10],tot,vis[maxn+10],n,m;
    
    void time() {cerr << (double) clock()/CLOCKS_PER_SEC << endl;}
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++) {
    		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
    		for(int j=1;j<=tot&&i*pri[j]<maxn;j++) {
    			vis[i*pri[j]]=1;
    			if(!(i%pri[j])) {mu[i*pri[j]]=0;break;}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}//time();write(tot);
    	for(int i=1;i<=tot;i++)
    		for(int j=1;j*pri[i]<maxn;j++) sum[j*pri[i]]+=mu[j];
    	for(int i=1;i<maxn;i++) sum[i]=sum[i]+sum[i-1];
    	//time();
    }
    
    signed main() {
    	sieve();int asd;read(asd);
    	//for(int i=1;i<=10;i++) write(sum[i]);
    	while(asd--) {
    		read(n),read(m);
    		if(n>m) swap(n,m);
    		int T=1,ans=0;
    		while(T<=n) {
    			int pre=T;T=min(n/(n/T),m/(m/T));
    			ans+=(n/pre)*(m/pre)*(sum[T]-sum[pre-1]);
    			T++;
    		}
    		write(ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    windows cmd 中获取当前时间并输出此时间
    使用windows批处理来让git每日自动更新代码
    拒绝垃圾文章 在 ejabberd 中使用 MySQL
    IOS调试lldb命令常用,po,
    IOS 多语言本地化 完美解决方案
    [转]Xcode封装.Bundle文件
    百度地图SDK引用问题 Symbol(s) not found for architecture armv64
    loaded the "ViewController" nib but the view outlet was not set. 处理方式
    initWithFrame 和 initWithCoder
    使用IB_DESIGNABLE与IBInspectable特性实现可在视图编辑器的功能栏中设置
  • 原文地址:https://www.cnblogs.com/hbyer/p/10051113.html
Copyright © 2011-2022 走看看