zoukankan      html  css  js  c++  java
  • 数论题目小记

    1.素数个数

    【题目描述】求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
    ", tot);
        }
        return 0;
    }
    

    2.视野

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

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

    【解题报告】

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

    求出(C * C) 矩阵中除((0,1),(1,0))以外所有互质点对
    互质点对是对称存在的,欧拉函数求出的是互质的数,所以欧拉出来的结果要x2;对角线不需要x2因为它没有对称点对(它在对称轴上)

    (刨除((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;  //这是简写,其实应写成(ans - 1) * 2 + 1  (这是因为对角线只有一个,所以要-1
          printf("%lld
    ",ans);
        }
        return 0;
    }
    

    (双倍经验) SDOI 仪仗队

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

    (从实际意义上来说,(N=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;
    }
    
  • 相关阅读:
    python语法基础-常用模块-re模块
    python语法基础-常用模块-长期维护
    python语法基础-函数-内置函数和匿名函数-长期维护
    python语法基础-函数-递归函数-长期维护
    python语法基础-函数-迭代器和生成器-长期维护
    python语法基础-函数-装饰器-长期维护
    python语法基础-函数-进阶-长期维护
    python语法基础-函数-基础-长期维护
    Python之路--目录
    mysql数据库-索引-长期维护
  • 原文地址:https://www.cnblogs.com/phemiku/p/11803571.html
Copyright © 2011-2022 走看看