定义及性质
定义:对于a、b两个整数,如果a和b的差能被m整除,那么a和b关于模m同余,记作a≡b(mod m)
对于整数a,b,c和自然数m、n,模m同余满足:
1、自反性:a≡a(mod m);
2、对称性:若a≡b(mod m),则b≡a(mod m);
3、传递性:若a≡b(mod m),b≡c(mod m),则a≡c(mod m);
4、同加性:若a≡b(mod m),则a+c≡b+c(mod m);
5、同乘性:若a≡b(mod m),则a*c≡b*c(mod m)
若a≡b(mod m),c≡d(mod m),则a*c≡b*d(mod m);
6、同幂性:若a≡b(mod m),则an≡bn(mod m);
7、推论1:a*b mod k=(a mod k)*(b mod k)mod k;
8、推论2:若a mod p=x,a mod q=x,p、q互质,则a mod p*q=x
证明:设a div p=k1,b div q=k2
∴a=p*k1+x,b=k2*q+x
∴p*k1=q*k2
∵p、q互质
∴k1÷q必定为整数,即q|k1
∴a=k*p*q+x
例1:Semi-prime H-numbers
形如4n+1的数称为H数,乘法在H数是封闭的。在这个集合中只能被1和本身整数整除的数称为H-素数,其余为H-合数。定义H-合成数为能且只能分解为2个H-素数的H-合数,求0~h中H-合成数的个数。
我们先考虑如何快速筛出H-素数,由于乘法在H数内封闭进行,并且有以下结论:
1、两个H数乘起来一定是H数
证明:我们设第一个H数等于4a+1,另一个为4b+1
∴(4a+1)(4b+1)=16ab+4a+4b+1=4(4ab+a+b)+1
∴乘积为H数
2、对于一个H-合数,必定可以分解为若干个H-素数的乘积。
3、对于一个H-素数,它的倍数一定是H-合数
有了以上结论,我们就可以利用类似线性筛的方法,把H-素数筛出来,不过还有一点需要解决,因为乘法封闭进行,因此H-素数的倍数也不是正常意义上的倍数,只是(4n+1),其中n为正整数。
代码
#include<iostream> #include<cstdio> using namespace std; const int N=1e6+10; int prime[100005],sum[N]; bool v[N],is[N]; int main() { int cnt=0; for(int i=5;i<N;i+=4) { if(!v[i])prime[++cnt]=i; for(int j=i*5;j<N;j+=i*4) v[j]=1; } // cout<<cnt<<endl; for(int i=1;i<=cnt;i++) for(int j=1;j<=i&&prime[i]*prime[j]<N;j++) is[prime[i]*prime[j]]=1; for(int i=1;i<N;i++) sum[i]=sum[i-1]+is[i]; int x; while(~scanf("%d",&x)&&x) printf("%d %d ",x,sum[x]); }