HDU

来源:互联网 发布:如何筛选重复数据 编辑:程序博客网 时间:2024/06/05 11:12
As we know, any positive integer C ( C >= 2 ) can be written as the multiply of some prime numbers:
    C = p1×p2× p3× ... × pk
which p1, p2 ... pk are all prime numbers.For example, if C = 24, then:
    24 = 2 × 2 × 2 × 3
    here, p1 = p2 = p3 = 2, p4 = 3, k = 4

Given two integers P and C. if k<=P( k is the number of C's prime factors), we call C a lucky number of P.

Now, XXX needs to count the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of a given P ( "gcd" means "greatest common divisor").

Please note that we define 1 as lucky number of any non-negative integers because 1 has no prime factor.




Input


The first line of input is an integer Q meaning that there are Q test cases.
Then Q lines follow, each line is a test case and each test case contains three non-negative numbers: n, m and P (n, m, P <= 5×105. Q <=5000).



Output


For each test case, print the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of P.


Sample Input
210 10 010 10 1
Sample Output
63 
93 


还是老样子,设 f(d) 为 gcd( a, b )=d 的数目,则F( d ) 为 gcd (a , b) 是 d 的倍数的数目,则F(d)就是(n/d)*(m/d)
然后有:(设 miu[ ] 是莫比乌斯函数)
f(1)=miu(1)*F(1)+miu(2)*F(2)+.........+miu(p1*p2*......*pi)*F(p1*p2*.......*pi)
f(2)=miu(1)*F(1*2)+miu(2)*F(2*2)+..........+miu(p1*p2*.....*pj)*F(p1*p2*.......*pj*2)

………………

f(d)=miu(1)*F(1*d)+miu(2)*F(2*d)+..........+miu(p1*p2*.....*pk)*F(p1*p2*.......*pk*d)

然后把 f(i) 中的质因子个数小于等于 p 的 i 对应的 f(i)加起来就得到 ans=f(1)+f(2)+.....+f(i)+........  =  a(1)*F(1)+a(2)*F(2)+.......+a(i)*F(i)+.......
其中a(i)为 i 相同的F(i)对应的各种  miu(i / j)的和。。。。。emmm…… 也就是说,对于一个 j ,筛出他的倍数 i ,则这个 j 对 F(i) 的贡献为 a( i )+=miu(i / j)。。。
然后莫比乌斯函数求和啊分段把 F(i) 加起来啊就完了
(我好没用实在讲不清楚。。。。。。。。)
当然,同时还要注意 gcd 是不是 lucky  number ,也就是限制其质因子个数小于等于 p
这个时候我们可以开一个二维数组 a[ i ][ j ]  表示 i 的倍数中质因子个数至多为 j,用这个数组来存对应的莫比乌斯函数的和
以下 K[ i ] 表示 i 的质因子有多少个,这个题他时间卡的紧(反正我是这么觉得),所以 K 数组不要用传统的那种一个一个遍历素数表的方法打表,会T的
可以跟着素数表直接打出来,这个比较快。
还有,以下 F[ i ][ j ] 即上述的  a[ i ][ j ]

#include <iostream>#include <stdio.h>#include <math.h>#include <string.h>#include <vector>#include <algorithm>#include <map>using namespace std;typedef long long LL;const LL MOD=1e9+7;#define fi first#define se secondconst int MAXN=1000000+23;LL prime[MAXN],total,miu[MAXN];bool isprime[MAXN];LL F[MAXN][23],K[MAXN];void make(){    int m=MAXN-3;    memset(isprime,true,sizeof(isprime));    memset(K,0,sizeof(K));    total=0;    isprime[0]=isprime[1]=false;    miu[1]=1;    for(int i=2;i<=m;i++)    {        if(isprime[i]){prime[++total]=i;miu[i]=-1;K[i]=1;}        for(int j=1;j<=total&&prime[j]*i<=m;j++)        {            K[i*prime[j]]=K[i]+1;            isprime[i*prime[j]]=false;            if(i%prime[j])            {                miu[i*prime[j]]=-miu[i];            }            else            {                miu[i*prime[j]]=0;                break;            }        }    }    miu[0]=0;//    for(int i=1;i<=m;i++)miu[i]+=miu[i-1];}LL n,m,p;void Init(){    LL m=5e5+230,_max=0;    for(LL i=1;i<=m;i++)    {        _max=max(_max,K[i]);        for(int j=1;j*i<=m;j++)        {            F[j*i][K[i]]+=miu[j];        }    }    for(int j=1;j<=m;j++)    {        for(int i=1;i<=_max;i++)        {            F[j][i]+=F[j][i-1];        }    }    for(int i=0;i<=_max;i++)    {        for(int j=2;j<=m;j++)        {            F[j][i]+=F[j-1][i];        }    }}int main(){    make();    Init();    int T;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld",&n,&m,&p);        if(p>18)        {            printf("%lld\n",n*m);            continue;        }        if(n>m)swap(n,m);        LL ans=0;        for(LL i=1,last=0;i<=n;i=last+1)        {            last=min(n/(n/i),m/(m/i));            ans+=(F[last][p]-F[i-1][p])*((n/i)*(m/i));        }        printf("%lld\n",ans);    }    return 0;}
emmmm............我才刚开始莫比乌斯专题,对每个题目的理解度不高,比如这个题目写的博客就和大佬们差距灰常大,所以请各位多多指正在下文意不清或者是有错误的地方
。。。。。。。(怀疑人生中)


原创粉丝点击