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.
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.
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).
210 10 010 10 1
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............我才刚开始莫比乌斯专题,对每个题目的理解度不高,比如这个题目写的博客就和大佬们差距灰常大,所以请各位多多指正在下文意不清或者是有错误的地方
。。。。。。。(怀疑人生中)
阅读全文
0 0