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 质因数分解
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
整数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
小明一天在做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
如果一个素数,依次去掉最高位得到一个数,这个数无前导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
如果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]);