2021.08.02(筛质数、分解质因数、快速幂)


1.1292. 哥德巴赫猜想 - AcWing题库

#include
#include
#include
#include
using namespace std;
const int maxn = 10000001;
bool vis[maxn]; // 0 为素数 1 为非素数
int tot, phi[maxn], prime[maxn];

void CalPhi() {
    vis[1] = 1, phi[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) prime[tot++] = i, phi[i] = i - 1;
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > maxn) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
int main(){
    int n;
    CalPhi();
    while(~scanf("%d",&n)){
        if(n==0){
            break;
        }
        int flag=0;
        for(int i=0;i){
            if(prime[i]%2==1&&vis[n-prime[i]]==0){
                printf("%d = %d + %d\n",n,prime[i],n-prime[i]);
                flag++;
                break;
            }
        }
        if(!flag){
            printf(" Goldbach's conjecture is wrong.\n");
        }
    }
}

注:注意标记质数的vis数组和prime数组两者的区别:

vis[i]=0/1:i是否是素数

prime[i]=j:第i个素数是j

2.1293. 夏洛克和他的女朋友 - AcWing题库

#include
#include
#include
#include
using namespace std;
const int maxn = 10000001;
bool vis[maxn]; // 0 为素数 1 为非素数
int tot, phi[maxn], prime[maxn];

void CalPhi() {
    vis[1] = 1, phi[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) prime[tot++] = i, phi[i] = i - 1;
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > maxn) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
int main(){
    int n;
    CalPhi();
    scanf("%d",&n);
    if(n==1){
        printf("1\n");
        printf("1\n");
    }else if(n==2){
        printf("1\n");
        printf("1 1\n");
    }else{
        printf("2\n");
        for(int i=2;i<=n+1;i++){
            if(vis[i]==0){
                printf("1 ");
            }else{
                printf("2 ");
            }
        }

    }
}

注:此题就是需要转换一下想法,主要是想明白只要是素数就输出1,只要是合数就输出2,即可

3.196. 质数距离 - AcWing题库

#include
#include
#include
#include
using namespace std;
#define int long long
const int maxn = 5e4+10;;
const int maxx=1e6+10;
bool vis[maxn]; // 0 为素数 1 为非素数
int tot, phi[maxn], prime[maxn];
int num[maxx]={0};
void CalPhi() {
    vis[1] = 1, phi[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) prime[tot++] = i, phi[i] = i - 1;
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > maxn) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
int p[maxx]={0};
signed main(void){
    CalPhi();
    int a,b;
    while(~scanf("%lld %lld",&a,&b)){
        memset(num,0,sizeof num);
        memset(p,0,sizeof p);
        //利用质数表筛选出区间中的合数
        for(int i=0;i){
            if(prime[i]>=b){
                break;
            }
            for(int j=a/prime[i];j*prime[i]<=b;j++){
                if(j<2){
                    continue;
                }
                num[j*prime[i]-a]++;
            }
        }
        
        //通过合数的标记存入区间中的质数
        int minn=0,maxp=0;
        int flag=0;
        for(int j=0;j<=b-a;j++){
            if(num[j]==0&&j+a>1){
                p[flag++]=j+a;
            }
        }
        
        //找最大最小的问题
        for(int i=1;i+1){
            if(p[i+1]-p[i]>p[maxp+1]-p[maxp]) maxp=i;
            if(p[i+1]-p[i]1]-p[minn]) minn=i;
        }
        if(flag<2){
            printf("There are no adjacent primes.\n");
        }else{
            printf("%lld,%lld are closest, %lld,%lld are most distant.\n",p[minn],p[minn+1],p[maxp],p[maxp+1]);
        }

    }
}

注:一直tle的原因就是多组数读入的时候最好不要while(1)然后再进入循环体中进行读取,最好是通过while(~scanf("%d",&a))这样读入,不然第一种就会一直tle

4.1289. 序列的第k个数 - AcWing题库

#include
#include
#include
#include
using namespace std;
#define int long long
const int maxn = 1e6+10;;
const int maxx=1e6+10;
const int mod=200907 ;
bool vis[maxn]; // 0 为素数 1 为非素数
int tot, phi[maxn], prime[maxn];
void CalPhi() {
    vis[1] = 1, phi[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) prime[tot++] = i, phi[i] = i - 1;
        for (int j = 0; j < tot; ++j) {
            if (i * prime[j] > maxn) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
inline long long Pow(long long a, long long n, long long m) {
    long long t = 1;
    for (; n; n >>= 1, a = (a * a % m))
        if (n & 1) t = (t * a % m);
    return t % m;
}
signed main(void){
    int t;
    scanf("%lld",&t);
    while(t--){
        int a,b,c,k;
        scanf("%lld %lld %lld %lld",&a,&b,&c,&k);
        if(b*2==a+c){
            printf("%lld\n",(a+((k-1)*(b-a))%mod)%mod);
        }else{
            printf("%lld\n",(Pow(b/a,k-1,mod)*a)%mod);
        }
    }


}

注:简单的快速幂的使用

5.1290. 越狱 - AcWing题库

#include
#include
#include
#include
using namespace std;
#define int long long
const int maxn = 1e6+10;;
const int maxx=1e6+10;
const int mod= 100003 ;
bool vis[maxn]; // 0 为素数 1 为非素数
int tot, phi[maxn], prime[maxn];
inline long long Pow(long long a, long long n, long long m) {
    long long t = 1;
    for (; n; n >>= 1, a = (a * a % m))
        if (n & 1) t = (t * a % m);
    return t % m;
}
signed main(void){
    int n,m;
    scanf("%lld %lld",&m,&n);
    printf("%lld\n",(Pow(m,n,mod)%mod-m*Pow(m-1,n-1,mod)%mod+mod)%mod);


}

注:注意一下当mod的时候减法的时候需要在后面再加一个mod谨防负数(x%mod-y%mod+mod)%mod

相关