CSU 1325: A very hard problem 莫比乌斯反演

1325: A very hard problem

Time Limit: 3 Sec   Memory Limit: 160 MB
Submit: 253   Solved: 58
[ Submit][ Status][ Web Board]

Description

CX老湿经常被人黑,被黑得多了,自己也就麻木了。于是经常听到有人黑他,他都会深情地说一句:禽兽啊!

一天CX老湿突发奇想,给大家出了一个难题,并且声称谁能够准确地回答出问题才能继续黑他,否则他就要反击了。

这个难题就是:

给出两个数p和q,接下来q个询问,每个询问给出两个数A和B,请分别求出:

一、有多少个有序数对(x,y)满足1<=x<=A,1<=y<=B,并且gcd(x,y)为p的一个约数;

二、有多少个有序数对(x,y)满足1<=x<=A,1<=y<=B,并且gcd(x,y)为p的一个倍数。

Input

只有一组测试数据。

第一行两个数:p和q。(1<p<10^7 ,1<q<1000。)

接下来有q行,每行两个数A和B。(1<A,B<10^7)

Output

输出共q行。每行两个数。用空格隔开。

分别表示题目描述中的两个对应的答案。

(x,y)=(2,3)和(x,y)=(3,2)被视为两个不同有序数对哦!

Sample Input

6 3
8 8
15 32
13 77

Sample Output

58 1
423 10
883 24

HINT

 对于64位整型请用lld,或者cin,cout。T_T


CSU_LQ

Source

题目:

     求满足1<= a <= x, 1<= b <= y,,gcd(a,b)是p的约数的,a,b的组合数。

分析:

    第二问直接除法就行

   第一问,用莫比乌斯可以再X^0.5内可以求出关于某个gcd的组合数:不会的话参考匡斌的博客,

下面两个题目也是莫比乌斯的,通过这两个题目就可以搜到kuangbin的博客,然后看相关的资料

http://www.cnblogs.com/kuangbin/archive/2013/08/21/3273440.html

下面是资料:

http://wenku.baidu.com/view/542961fdba0d4a7302763ad5.html

http://baike.baidu.com/link?url=1qQ-hkgOwDJAH4xyRcEQVoOTmHbiRCyZZ-hEJxRBQO8G0OurXNr6Rh6pYj9fhySI0MY2RKpcaSPV9X75mQv0hK

;以下是我写的两题莫比乌斯的博客:

http://blog.csdn.net/firenet1/article/details/47171991

http://blog.csdn.net/firenet1/article/details/47171991

看完以上两个博客,知道分块处理莫比乌斯可以根号的时间复杂度来做。----------但是需要预处理u函数的前缀和

分析;只要求出p的所有因素,对每个因数求有多少对a,b的gcd是它的就行,但是因素个数很多!

1000组case,还有根号的复杂度就是1000*sqrt(x)*C > 1000,000,000会超时,

那么考虑把所有的因素的预处理掉。

举例:如果1,2是p的因数

f(1) = u(1)* F*(1) + u(2) * F(2) + u(3) *F(3) + u(4)*F(4) + .....

f(2) = u (1) * F(1*2) + u(2) * F(2*2) +.......

可以发现如果把1,2的函数一起处理,那么需要把F(2),F(4),F(6).....的系数处理掉,那么

F(2)的系数就是u(1)+u(2) 

F(4)的系数就是u(4)+u(2)

可以看出因子1需要处理O(p)(p是数据范围的意思)个系数

因子2需要处理O(p/2)个系数,那么总共的次数越是p*log(log(p))的


#include <iostream>
#include <string.h>
#include <cmath>
#include <stdio.h>
#define maxn 10000100
using namespace std;
int m,cnt;
long long n;
int mu[maxn];
int prime[maxn],vis[maxn];
int sum[maxn];
long long ans,sav[100000];
void init(){
	memset(vis,0,sizeof(vis));
	cnt=0;
	mu[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i]){
			prime[cnt++]=i;
			mu[i]=-1;
		}
		for(int j=0;j<cnt&&i*prime[j]<maxn;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]) mu[i*prime[j]]=-mu[i];
			else {
				mu[i*prime[j]]=0;
				break;
			}
		}
	}
//莫比乌斯函数

}

int main(){
	long long a,b;
	scanf("%lld%d",&n,&m);
	init();
	int k=0;
	for(int i=1;i*i<=n;i++) //预处理因素
		if(n%i==0){
			sav[k++]=i;
			if(i!=n/i)
			sav[k++]=n/i;
		}
    memset(sum,0,sizeof(sum)); //合并所有因子对应的u函数的前缀和
    for(int i = 0;i < k; i++){
        for(int j = 1;j*sav[i] < maxn; j++)
            sum[j*sav[i]] += mu[j];
    }
	for(int i = 1;i < maxn; i++){
		sum[i] = sum[i-1] + sum[i];
	}
	for(int i=0;i<m;i++){
		scanf("%lld%lld",&a,&b);
		ans=0;
        int N = a, M = b,l;
        if(N > M) swap(N,M);
        for(int j = 1; j <= N ;j = l + 1) //分快加速
        {
            l= min(N/(N/j),M/(M/j));
            ans += (long long)(sum[l]-sum[j-1])*(N/j)*(M/j);
        }

		long long tmp=a/n;
		tmp=b/n*tmp;
		printf("%lld %lld\n",ans,tmp);
	}
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值