打卡湘大OJ第4天

本文介绍了几种计算区间内素数个数的方法,包括直接计数和预处理数组。此外,还讨论了欧拉函数的实现,用于计算小于等于给定数的互质数个数。接着,文章讲解了求最大公约数(GCD)的算法,以及如何找出无暇素数,即除了1和自身以外不含其他质因数的素数。最后,文章涵盖了质因数分解和A+BVIII问题,后者涉及寻找特定数值范围内的因子个数。
摘要由CSDN通过智能技术生成

目录

1.求区间内素数个数问题

2.欧拉函数

 3.GCD

4.无暇素数

 5.质因数分解

6.A+BVIII

7.Alice and Bob


1.求区间内素数个数问题

法1:

#include <stdio.h>
#include <stdlib.h>
#define p 1000005
#include <stdio.h>
int num[p];
int main()
{
     int i,j;
     for(i=2;i<p;i++)
        num[i]=1;
     for(i=2;i<p;i++)
     {
         if(num[i]){
            for(j=2;i*j<p;j++){
                num[i*j]=0;
            }
         }
     }//此时,所有值为1的num[i]中的i为素数
     for(i=1;i<p;i++){
        num[i]=num[i]+num[i-1];
     }//num[i]为从1到i的素数个数
     int a,b,n,temp;
     scanf("%d",&n);
     while(n--){
        scanf("%d%d",&a,&b);
        if(a>b){
            temp=a;
            a=b;
            b=temp;
        }
        printf("%d\n",num[b]-num[a-1]);
     }
     return 0;
}

 法2:

#include <stdio.h>
#include <stdlib.h>
#define p 1000005
#include <stdio.h>
int num[p];
int main()
{
     num[0]=1;
     num[1]=1;//1代表非素数,0代表素数
     int i,j;
     for(i=2;i<p;i++){
        if(!num[i]){
            for(j=2*i;j<p;j=j+i){
                 num[j]=1;
          }
        }
     }


     int a,b,n,temp;
     scanf("%d",&n);
     while(n--){
        scanf("%d%d",&a,&b);
        if(a>b){
            temp=a;
            a=b;
            b=temp;
        }
        int count=0;
        for(int i=a;i<=b;i++){//直接在a和b范围内数素数的个数
            if(!num[i])
                count++;
        }
        printf("%d\n",count);
     }
     return 0;
}

法3:

#include<cstdio>
#include<algorithm>
using namespace std;
int s[1000050];
int noprime[1000050];
int main() {
	noprime[0] = 1; 
	noprime[1] = 1; 
	for(int i = 2; i<= 1000000; i++) {
		if(!noprime[i]) {
			for(int j = 2*i; j<= 1000000; j+=i) {
				noprime[j] = 1;
			}
		}
	}
	s[0] = 0;
	for(int i = 1; i<= 1000000; i++) {
		if(noprime[i]==1) s[i] = s[i-1];
		else if(noprime[i]==0) s[i]=s[i-1]+1;
	}
	int k;
	scanf("%d",&k);
	while(k--) {
		int a,b;
		scanf("%d%d",&a,&b);
		if(a>b) swap(a,b);
		if(a==0) printf("%d\n",s[b]);
		else printf("%d\n",s[b]-s[a-1]);
	}
}

参考:湘潭大学OJ-1098求区间内素数个数问题_xtuzxj的博客-CSDN博客

2.欧拉函数

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main()
{
     int n;
     while(scanf("%d",&n)!=EOF){
        if(n==0) break;
        if(n==1)
        {printf("0");
         continue;
        }
        int ans=n;
        for(int i=2;i<=sqrt(n);i++){
            if(n%i==0){
                while(n%i==0){
                    n=n/i;
                }
                ans/=i;
                ans*=(i-1);
            }
        }
        if(n!=1){
            ans/=n;
            ans*=(n-1);
        }
        printf("%d\n",ans);
     }

}

 3.GCD

解法
与六互素就是不能是二的倍数也不能是三的倍数,所以这道题就是求一个范围内不是二和三的倍数的数字的个数。一个数(假设这个数是b)除以三(取整)就是[1, b]内的三的倍数的个数,同理,一个数除以二(取整)就是[1, b]二的倍数的个数。但是,有些数字即是二的倍数,又是三的倍数,这时候要把这些数字减去。求[a, b]区间内的这样的数的个数可以这样做,先求[1, b]内这样的数字的个数。再求[1, a-1]区间内这样数字的个数

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int fun(int a, int b) {
	int a3 = b / 3;
	int a2 = b / 2;
	int a6 = b / 6;
	return b - (a3 + a2 - a6);
}
int main(int argc, char const **argv) {
	int K;
	scanf("%d",&K);
	while(K--) {
		int a,b;
		scanf("%d%d",&a,&b);
		int s = fun(1, b);
		int m = fun(1, a - 1);
		printf("%d\n", s-m);
	}
	return 0;
}

 参考:XTUOJ-1296-GCD_轨迹 ‎‎ ‎‎的博客-CSDN博客

4.无暇素数

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int judge(int x) {
    if(x==1) return 0;//不是素数
    for(int i=2;i<=sqrt(x);i++){
        if(x%i==0)
            return 0;
    }
	return 1;
}
int main() {
	int K;
	scanf("%d",&K);
	while(K--) {
		int n;
		scanf("%d",&n);
		int m=n;
		int flag=1;
		int an=1;
		while(m>0){//计算该数有多少位,并判断是否有前导0(包括最后一位是不是0)
            if(m%10==0){
                flag=0;//有0
            }
            an*=10;
            m/=10;
		}
		if(flag==1){
            for(int i=an;i>=10;i/=10){//从该数本身,到依次去除最高位得到的数
                if(judge(n%i)==0){
                    flag=0;
                    break;
                }
            }
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

 参考:湘大OJ1295Flawless Prime_xtuzxj的博客-CSDN博客

 5.质因数分解

从i=2到 i*i<=n循环,当遇到一个n%i=0的情况,就算是找到了一个质因数。注意最后n不是0的情况。比如说 求6得质因子个数,当i*i<=6时结束循环,此时i一定是小于3的,按照我们的分析 6应该包含2个质因子(2和3),所以当循环完毕时,要判断一下 n此时的值,若为1 说明已经把质因数找完,若不为1,那么剩下的一定是个质数。

这个题还要注意输出的问题,使用”^”表示幂,”*”表示乘。

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main() {
	int n;
	while(scanf("%d",&n)!=EOF) {
		int an = 0;//an这个变量在存储找到的不同质因数的个数
		for(int i = 2; i*i<= n; i++) {
			if(n%i==0) {
				int count = 0;//count这个变量储存每个质因数的个数
				while(n%i==0) {
					count++;
					n /= i;
				}
				if(an!=0) printf("*");
				if(count!=1) printf("%d^%d",i,count);
				else if(count==1) printf("%d",i);
				an++;
			}
		}
		if(an==0) printf("%d\n",n);
		else {
			if(n!=1) printf("*%d\n",n);
			else if(n==1) printf("\n");
		}
	}
	return 0;

}

6.A+BVIII

求能被整除的数其实就是求因子,比如说 一个数中质因数分解后有3个2,也就是 2^3 × \times ×(此处省略一堆质因数分解),那么1(2的0次方),2(2的1次方),4(2的2次方),8(2的3次方)都是这个数的因数,也就是都可以被这个数整除,那么假如说 一个数被分解成了 2∧3 × \times × 3∧2,那么其实他就有(3+1) × \times ×(2+1)个因子,因为由2构成的因子有4个(1,2,4,8) ,由3构成的因子就有3个(1,3,9)所以这些个数乘起来也是那个数的因子。

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main() {

	int k;
	scanf("%d",&k);
	while(k--) {
		int a,b;
		scanf("%d %d",&a,&b);
		int x = a+b;
		int ans = 1;//因为要进行×的运算,所以要初始化为1
		for(int i = 2; i*i <= x; i++) {
			if(x%i==0) {
				int count = 0;
				while(x%i==0) {
					count++;
					x /= i;
				}
				ans *= (count+1);
			}
		}
		if(x!=1) printf("%d\n",ans*2); //如果最后剩下的数不是1 那么一定还有一个质因子
		else printf("%d\n",ans);
	}

}

参考:湘大1218 A+BVIII_xtuzxj的博客-CSDN博客

7.Alice and Bob

n位数最大数是10^n-1,这个数除m向下取整得到的商再减去n-1位数最大的数除以m得到的商就是他们都喜欢的数。注意数的范围别溢出就好

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main() {

	int k;
	scanf("%d",&k);
	unsigned long long temp;
	while(k--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        temp=(unsigned long long)pow(10,n)-1;
        unsigned long long cnt=temp/m-temp/10/m;
        if(n==1){
            cnt++;
        }
        printf("%ld\n",cnt);

    }
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值