题意:给你一个超级大的数K(1e100),这个数是两个大素数相乘得到的。给你一个数L,K的两个素因子中较小的那个如果比L小就输出BAD和那个素因子,否则输出GOOD
思路:同余定理。用字符数组储存这个数,按千进制转换后储存在int数组里。
之后同余定理高精度取模。
比如1234%m=(1*1000+2*100+3*10+4)%m=(((1*10+2)*10+3)*10+4)%m=(((1*10+2)%m*10+3%m*10+4)%m
其实同余定理就两个最主要的应用:
(a+b)%m=a%m+b%m
(a*b)%m=(a%m)*(b%m)
当然,这道题还是看大神的博客写的:https://blog.csdn.net/lyy289065406/article/details/6648530
代码如下:
WA了很久,主要有两个原因:对同余定理的理解不对,存转为千进制的数组K开的太小了。。。
#include <cstring>
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MAXN=2e6+10;
int prime[MAXN];
char s[110];
int k[110];//开k[20]一直挖。。。k[20]只能算到60位左右
int bit;
void getPrime()//素数筛,MAXN的范围是我试出来的,这样能保证算出所有不大于1e6的素数
{
memset(prime,0,sizeof(prime));
for(int i=2; i<=MAXN; i++)
{
if(!prime[i])prime[++prime[0]]=i;
for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++)
{
prime[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
}
void change()
{
memset(k,0,sizeof(k));
int lens=strlen(s)-1;
bit=0;
while(lens>=0)
{
int t=3,num=1;//每三位存一次,即转为千进制
//ans=s[lens--]-'0';
while(t--&&lens>=0)
{
k[bit]=k[bit]+num*(s[lens--]-'0');
num*=10;//bit++写着方便,局部有序,全局倒序地存。
}
bit++;
}
bit--;
}
int main()
{
getPrime();
//cout<<prime[80000]<<endl;
int L;
while(scanf("%s%d",s,&L)&&L)
{
//cout<<strlen(s)<<endl;
bit=0;
change();
//cout<<"BIT "<<bit<<endl;
//bit此时是千进制下最后一位的下标
for(int i=1;prime[i]<L;i++){
int ans=0;
for(int j=bit;j>=0;j--)//倒着存的数,j循环也要倒着来哦
ans=(k[j]+1000*ans)%prime[i];//同余定理的精髓!!多看几眼
if(ans==0)
{
cout<<"BAD "<<prime[i]<<endl;
goto endd;
}
}
cout<<"GOOD"<<endl;
endd:;
}
return 0;
}