赛克oj 1541(线性筛、约数个数)

赛氪OJ-专注于算法竞赛的在线评测系统 (saikr.com)

题目描述

小明在学校学了质数和合数的知识后,便想知道对于任意的一个数N,将其拆分为一个质数与一个合数相加的结果,有几种拆法?

但后来想想又觉得太简单了,于是他追加了一些条件,合数要继续拆分为两个数相乘的形式才行,那么满足以上条件的关于N的等式有几种?

换句话来讲,你需要找出满足以下条件的等式的数量:

𝐴×𝐵+𝐶=𝑁(𝐴,𝐵>0,𝐶≥2,𝐴×𝐵A×B+C=N(A,B>0,C2,A×B 结果为合数,𝐶C 为质数))

需要注意的是,小明根据质数的定义,把11也归为了合数,所以1×11×1也可以算一个𝐴×𝐵A×B 。

输入

输入格式:

  • 输入一行一个数n

输出

输出格式:

  • 输出一行一个数,表示等式数量


    线性筛模板来自线性筛求 约数个数 与 约数和 - 糖豆爸爸 - 博客园 (cnblogs.com)
  •  1 #define IO std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
     2 #define bug(x) cout<<#x<<" is "<<x<<endl
     3 #include <bits/stdc++.h>
     4 #define iter ::iterator
     5 using namespace  std;
     6 typedef long long ll;
     7 typedef pair<int,int>P;
     8 #define pb push_back
     9 #define mk make_pair
    10 #define se second
    11 #define fi first
    12 #define rs o*2+1
    13 #define ls o*2
    14 const int N = 2e7+5;
    15 
    16 int primes[2000000], cnt; // primes[]存储所有素数
    17 bool st[N];         // st[x]存储x是否被筛掉
    18 int d[N];           // d[x]表示x的约数个数
    19 int num[N];         // num[x]表示x的最小质因数的个数
    20 int n;
    21 //欧拉筛法+求约数个数
    22 void get_primes(int n) {
    23     d[1] = 1; // 1的约数只有1个,这个比较特殊
    24 
    25     for (int i = 2; i <= n; i++) {
    26         if (!st[i]) {
    27             primes[cnt++] = i;
    28             // i是质数
    29             d[i] = 2;   //约数个数是2个,一个是1,另一个是i
    30             num[i] = 1; //最小质因子个数是1,最小质因子就是自己i
    31         }
    32 
    33         for (int j = 0; i <= n/primes[j]; j++) {
    34             st[i * primes[j]] = true;
    35             if (i % primes[j] == 0) {
    36                 d[i * primes[j]] = d[i] / (num[i] + 1) * (num[i] + 2);
    37                 num[i * primes[j]] = num[i] + 1;
    38                 break;
    39             } else {
    40                 // d[i * primes[j]] = d[i] * d[primes[j]]; 等价于下面的代码 
    41                 d[i * primes[j]] = d[i] * 2;
    42                 num[i * primes[j]] = 1;
    43             }
    44         }
    45     }
    46 }
    47 
    48 int main() {
    49     //scanf("%d", &n);
    50     //n=2e7;
    51     //cin>>n;
    52     IO;
    53     cin>>n;
    54     get_primes(n-1);
    55     //输出1~n之间所有数字的约数个数
    56     ll ans=0;
    57     for(int i=0;i<cnt;i++){
    58         int x=primes[i];
    59         int y=n-x;
    60         if(y==1){
    61             ans++;
    62             continue;
    63         }
    64         if(st[y])ans+=d[y];
    65     }
    66     cout<<ans<<endl;
    67     
    68     
    69     //for (int i = 1; i <= n; i++) printf("%d %d\n", i, d[i]);
    70     return 0;
    71 }

     

posted @ 2024-05-27 17:40  Venux  阅读(4)  评论(0编辑  收藏  举报