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

来源:互联网 发布:武汉ui知乎 编辑:程序博客网 时间:2024/06/02 21:20

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 38 815 3213 77

Sample Output

58 1423 10883 24

HINT

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


CSU_LQ

Source

CSU Monthly 2013 Oct.

题目:

     求满足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 10000100using 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 0