湘大 XTU OJ :1076 素数、1089 质因数分解、1139 D_Prime、 1218 A+B VIII、1295 Flawless Prime、1237 Prime Twins

链接:

1076 素数

题目:

Description

对于大于1的自然数,如果n为素数,那么所有大于1且不大于n的平方根的自然数都不能整除n,反之亦然。所以我们可以通过测试来确定n是否为素数。现在给出n,要你求是否为素数,是输出Yes,否则输出No

每行一个正整数n,n<=2^32-1如果n为0,则输入结束。判断n是否为素数

每行输出一个用例的结果,如果是输出"Yes",否则输出“No”

Sample Input

2
3
4
5
6
0

Sample Output

Yes
Yes
No
Yes
No

Source

ericxie

代码:

#include

using namespace std;

bool isprime(long long a)
{
	if(a<2)	return false;
	
	for(long long i=2;i*i<=a;i++)
		if(a%i==0)	return false;
	
	return true;
}

int main()
{
	long long n;
	while(cin>>n,n!=0)
	{
		if(isprime(n))	printf("Yes\n");
		else	printf("No\n");
	}
	
	return 0;
}

总结:

1.是一个计算素数的算法模板:

bool isprime(long long a)
{
	if(a<2)	return false;
	
	for(long long i=2;i*i<=a;i++)
		if(a%i==0)	return false;
	
	return true;
}

这里需要注意的是,这里是超过了int的范围的,int 的范围是-2^31~2^31-1,-2147483648 - 2147483647,大概是2*10e9 

2.奇怪的是循环输入的时候只能用cin输入,用scanf输入会超时,不知道为啥

按道理来说scanf输入应该更快

 3.改成%I64d就可以解决上面的问题


 1089 质因数分解

链接

1089 质因数分解

题目

Description

任意一个正整数可以分解成唯一的质因数的乘积,给出正整数,请计算出它的质因数分解式。

输入

每行一个正整数2<=n<=10^8

输出

每行输出一个对应结果。使用”^”表示幂,”*”表示乘,质因子应该按从小到大的顺序输出,如果某一个质因子只有一次,那么就不要输出它的幂。

Sample Input

2

6

36

Sample Output

2

2*3

2^2*3^2

代码:

#include

using namespace std;

int main()
{
	int n;
	
	while(~scanf("%d",&n))
	{
		int cnt1=0;
		
		for(int i=2;i*i<=n;i++)
		{
			if(n%i==0)
			{
				while(n%i==0)
				{
					n/=i;
					cnt1++;
				}
				
//				if(cnt1!=1)	printf("%d^%d*",i,cnt1);
//				else if(cnt1==1&&n!=1)	printf("%d*",i);
//				else	printf("%d",i);
				
				if(cnt1!=1&&n==1)	printf("%d^%d",i,cnt1);
				if(cnt1!=1&&n!=1)	printf("%d^%d*",i,cnt1);
				if(cnt1==1&&n==1)	printf("%d",i);
				if(cnt1==1&&n!=1)	printf("%d*",i);
				
				cnt1=0;
			}
		}
		
		if(n!=1)	printf("%d",n);
//		else	printf("\n");
		
		printf("\n");
	}
	
	return 0;
}

总结

1.主要是考察对于题目要求的实现的准确和完整性,最难的就是要判断清楚什么情况下输出^,什么情况下输出* 

2.声明:初学c语言的同学,看我这个代码,把这两行

#include

using namespace std;

 看成这一行就行

#include

3.质因数分解,其实从小到大都进行分解,分解到不能分解,再分解剩下的因子,那么每一个因子都会是质因子

4.每一次结束之后需要把幂指数归零

5.复杂情况讨论

(1)幂指数不是1,并且剩下的因子不是1,输出a^b*

(2)幂指数不是1,剩下的因子是1,输出a^b就结束就行

(3)幂指数是1,剩下的因子不是1,输出a*

(4) 幂指数是1,生剩下的因子是1,输出a就行

6.不断地调试代码,用输入输出调试,这种题目要么耐心调试试错,要么仔仔细细想清楚总共有多少种情况,双管齐下也行


1139 D_Prime

链接

1139 D_Prime

题目

 

题目描述

整数n=p*q,p和q为质数,且p≠q,我们称n为D-Prime,请写个程序判断一个数是不是D_Prime。

输入

第一行是一个整数K,表示样例的个数。以后每行是一个整数x,(1 ≤ x ≤ 100,000,000);

输出

每行输出一个样例的结果,如果是输出“Yes”,否则输出“No”。

样例输入

4 
30 
121 
21 
12

样例输出

No 
No 
Yes 
No

代码

#include

using namespace std;

bool isprime(int a)
{
	if(a<2)	return false;
	
	for(int i=2;i*i<=a;i++)
		if(a%i==0)	return false;
	
	return true;
}

int main()
{
	int t;
	scanf("%d",&t);
	
	while(t--)
	{
		int n;
		bool flag=false;
		scanf("%d",&n);
		
		for(int i=2;i*i<=n;i++)
		{
			if(n%i==0)
			{
				if(isprime(i)&&isprime(n/i)&&(i!=n/i))
				{
					flag=true;
					printf("Yes\n");
					break;
				}
			}
		}
		
		if(flag==false)	printf("No\n");
		
		//flag=false;
	}
	
	return 0;
}

总结

 1.先上一个判断素数模板

bool isprime(int a)
{
	if(a<2)	return false;
	
	for(int i=2;i*i<=a;i++)
		if(a%i==0)	return false;
	
	return true;
}

2.如果满足条件就输出答案即可

3.注意两个数乘法的要素,i*i<=n就可以了,超过根号之后的数其实和n/i是重复的,这样可以减少一些计算量 


 1218 A+B VIII

链接

1218 A+B VIII

题目

 

题目描述

小明一天在做a+b时,突然他想知道a+b能被哪些数整除了?比如说2+4=6,能整除6的数有1,2,3,6,一共4个。 请你帮他算一下,a+b的和能被几个数整除。

输入

第一行是一个整数K,表示样例的个数。 每个样例占一行,为两个整数a,b,(1≤a,b≤1e9)。

输出

每行输出一个样例的结果,为一个整数

样例输入

2
2 3
4 2

样例输出

2
4

代码

#include

using namespace std;

int main()
{
	int t;
	scanf("%d",&t);
	
	while(t--)
	{
		int a,b,c,sum=1,count=0;
		
		scanf("%d%d",&a,&b);
		c=a+b;
		
		for(int i=2;i*i<=c;i++)
		{
			count=0;
			
			if(c%i==0)
			{
				while(c%i==0)
				{
					c/=i;
					count++;
				}
			}
			
			sum*=(count+1);
		}
		
		if(c==1)	printf("%d\n",sum);
		else	printf("%d\n",sum*2);
	}
	
	return 0;
}

总结

1.事实上a+b只是一个外衣,我们实际上要使用的只有他们的和c

2.类似于一个数学结论:就像上一题一样(1089 质因数分解),把一个数字分解成为质因子和它的幂指数从零开始计算幂指数就需要把幂指数加一,类似于多项式一项一项去展开,每一个质因子乘以一个幂指数(从0开始计算到最大的幂指数),然后再乘以另一个质因子的类似的乘法式子

,使用这一行代码实现

sum*=(count+1);

3.如果最后还剩下一个幂指数为1的质因子,我们就需要把答案乘以2,因为从0开始计算到最大幂指数1,有两个数字

4.想清楚数学原理还是非常简单的一道题目 


1295 Flawless Prime

链接

1295 Flawless Prime

题目

题目描述

如果一个素数,依次去掉最高位得到一个数,这个数无前导0,并仍是素数的话,我们称其为“无瑕素数”。
比如317是素数,去掉最高位3得到17仍然是素数,再去掉最高位1得到7,仍然是素数,所以317是“无瑕素数”。
比如虽然107是素数,去掉最高位1得到7也是素数,但是因为存在前导0,所以这不是无瑕素数。
请写一个程序,判断某个素数是不是无瑕的。

输入

第一行是一个整数K,表示样例的个数。 以后每行一个整数n(2≤n≤1,000,000,000)。

输出

如果是无瑕素数,输出“Yes”,否则输出“No”。

样例输入

3
3
107
317

样例输出

Yes
No
Yes

代码 

#include

using namespace std;

bool isprime(int n)
{
	if(n<2)	return false;
	
	for(int i=2;i*i<=n;i++)
		if(n%i==0)	return false;
	
	return true;
}

bool zero(int n)
{
	int i=10;
	
	while(n)
	{
		if(n%i==0)	return false;
		else	n/=10;
	}
	
	return true;
}

int length(int n)
{
	int cnt=0;
	
	while(n)
	{
		n/=10;
		cnt++;
	}
	
	return cnt;
}

bool solve(int n)
{
	int l=length(n);
	
	for(int i=0,k=10;i

总结

1.题目的要求比较多,我们可以一个一个要求去分解

2.先上一个判断素数模板

bool isprime(int n)
{
	if(n<2)	return false;
	
	for(int i=2;i*i<=n;i++)
		if(n%i==0)	return false;
	
	return true;
}

3.前导零:如果有前导零就不满足题目的要求,我们知道一个数字模除10,就可以求出个位的数字,除以10,就可以把个位的数字扔掉,本来按照题目的要求是从最高位开始判断是不是有前导零,但是从最低位开始判断其实是非常便捷的,最低位(假设还没有除以10)假设是一个0,表示该数字是偶数,必定不符合素数的要求

4.计算数字有多少位:使用一个while循环+一个计数器就可以实现

5.设置一个解决问题的函数:循环该数字的长度这么多次,判断是否是素数,(注意,没有判断前导零,分开判断思路更加清晰),需要注意的是这里没有实际改变数字,还是从最低位开始,比如说该数字模除10,就是留下个位,模除100就是留下十位和个位,模除1000就是留下百位十位个位

if(!isprime(n%k))	return false;

如果按照题目要求来模拟,先把数字位数求出来,把数字位数作为10的幂指数,比如说本来是1234,4位数,10^4=1000,把1234模除1000,234,把1000除以10=100,234%100=34,100/10=10,34%10=4,事实上也可以实现题目的要求,所以这里怎么模拟其实都是可以的

6.主函数里面判断一下素数和前导零就可以了


 1237 Prime Twins

链接

1237 Prime Twins

题目

题目描述

如果n和n+2都是素数,我们称其为孪生素数,比如3和5,5和7都是孪生素数。 给你一个区间[a,b],请问期间有多少对孪生素数?

输入

第一行是一个整数K(K≤ 10000),表示样例的个数。 以后每行一个样例,为两个整数,a和b,1≤a≤b≤5000000。

输出

每行输出一个样例的结果。

样例输入

5 
1 3 
1 10 
1 100 
1 1000 
1 5000000

样例输出

0 
2 
8 
35 
32463

代码

#include

using namespace std;

const int N=5e6+10;

int a[N],s[N];

void start()
{
	a[0]=a[1]=1;
	
	for(int i=2;is[a])	printf("%d\n",s[b]-s[a]-1);
		else			printf("%d\n",s[b]-s[a]);
	}
	
	return 0;
}

总结

1.朴素的使用判断素数算法模板因为需要计算太多次数,所以直接超时了

2.用另外一种方法把非素数标记一下,这种时间复杂度比判断一个数是否是素数的时间复杂度要低,所以不会超时

for(int i=2;i

 事实上这种循环可以把所有的非素数标记为1,可以当作一个算法模板,核心思想就是把所有数字遍历一遍,再用另外一个循环,把已经遍历过的因子逐个加一遍,(不好用语言描述,直接看代码应该可以理解),加的是一个因子,那么这个数就一定是非素数,它至少有i这个因子

3.就像是求前缀和一样,把符合题目要求的全部找出来,然后增加计数器的数值,把计数器的数值保存在数组里面,每一次重置计数器的数值

int cnt=0;
for(int i=5;i

 4.真难想啊(bushi,s[b]-s[a]其实就是前缀和的思想,我们这里是把一对孪生素数存在了后面那个素数里面,我们[a,b],区间内有多少对孪生素数,是要求两个素数都在同一个区间,我们现在需要讨论的就是左边边界的几个元素,s[b]-s[a],表示的是a+1到b这之间所有的孪生素数对数(a就算和a-2可以构成孪生素数也不符合要求),需要注意,a+1是素数的话,a-1也是素数,就表示这两个素数组成一个孪生素数对,但是a-1不在区间范围内,所以需要进行一个讨论,s[a+1]-s[a]>0,表示a-1和a+1构成孪生素数,但是我们不能把这个计入答案,所以把答案减去1,否则直接输出答案

if(s[a+1]>s[a])	printf("%d\n",s[b]-s[a]-1);
else			printf("%d\n",s[b]-s[a]);

 湘大 XTU OJ :1076 素数、1089 质因数分解、1139 D_Prime、 1218 A+B VIII、1295 Flawless Prime、1237 Prime Twins_第1张图片

 

你可能感兴趣的:(算法竞赛,湘大,XTU,OJ,数据结构)