数论题目小记

吃可爱长大的小学妹 提交于 2019-12-03 16:57:49

素数个数

【题目描述】求n到n+m内的素数个数

【解题报告】

“数论题目有时复杂度看着很大,实际上并没有那么大”

详见代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6 + 3;
ll n, m, pr[N], tot, s[N];
bool vis[N];
int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%lld%lld", &n, &m);
        memset(vis, 0, sizeof vis);
        tot = m + 1;
        for (ll i = 2; i <= 1e6 && i <= n + m; i++)
            for (ll j = (n / i) * i; j <= n + m; j += i)  //保证跳到的都是合数
                if (j >= n && j != i && !vis[j - n]) {
                    vis[j - n] = 1; 
                    tot--;  //素数的个数等于总数-合数
                }
        printf("%lld\n", tot);
    }
    return 0;
}

视野

【传送门】 http://oj.ipoweru.cn/problem/70014

【题目大意】给定正整数\(C\),问从原点能看到几个坐标范围\(0<x,y<=C\)的整点。

【解题报告】

会被遮挡的是斜率相同的,也即\(\frac{y}{x}\)相同的坐标;而k作为分数可以约分,于是我们可以得到解决这道问题的思路:

求出\(C * C\) 矩阵中除\((0,1),(1,0)\)以外所有互质点对

(刨除\((0,1),(1,0)\)是题目要求,而下一道双倍经验题要求的范围不一样,要重新仔细思考范围嗷~)

到此,做法就呼之欲出了:欧拉函数求和。还有不明白就看代码吧。

#include <bits/stdc++.h>
const int N = 1e6 + 5;
#define int long long
using namespace std;
int t, c, n = 1e6, prime[N], phi[N], tot,ans;
bool vis[N];

void getprime() {
    phi[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!vis[i]) {
            prime[tot++] = i;
            phi[i] = i - 1;
        }
        for (int j = 0; j < tot && i * prime[j] <= n; ++j) {
            vis[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
}

signed main() {
    getprime();
    scanf("%lld",&t);
    while (t--) {
      ans = 0;
      scanf("%lld", &c);
      for (int i = 1; i <= c; i++)   ans += phi[i];
      ans = ans * 2 - 1;  //对角线只有一个,所以要-1
      printf("%lld\n",ans);
    }
    return 0;
}
(双倍经验) SDOI 仪仗队

要注意的是,题目中体委站的位置是\((1,1)\),不是原点;当 \(N = 1\)时,需要特判\(ans = 0\)

(对于$ φ(1)=1 \(,我的理解是:因为只有1和0互质,而0显然不在此题的矩阵范围内,所以\)ans = 0\(,从实际意义上来说,\)N=1$即矩阵只有体委一个人,他当然不可能看到其他人;

而上一题要求不计算\((0,1),(1,0)\)两个点,而1和1不互质,却要加上对角线,所以我们利用$ φ(1)=1 $的结果,却不是用的它原本的意思)

(个人观点,如有谬误,请在评论区指出,谢谢!)

#include <bits/stdc++.h>
const int N = 1e6 + 5;
#define int long long
using namespace std;
int t, c, n = 1e6, prime[N], phi[N], tot,ans;
bool vis[N];

void getprime() {
    phi[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!vis[i]) {
            prime[tot++] = i;
            phi[i] = i - 1;
        }
        for (int j = 0; j < tot && i * prime[j] <= n; ++j) {
            vis[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
}

signed main() {
      getprime();
      std::cin >> c;
      if(c == 1) {
        std::cout << "0";
        return 0;
      }
      for (int i = 1; i <= c - 1 ; i++)   ans += phi[i];
      ans = ans * 2 + 1;  
      std::cout << ans;
      return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!