zoukankan      html  css  js  c++  java
  • 洛谷 2158 数论 打表 欧拉函数

    #洛谷 2158 数论 递推 欧拉函数 打表找规律

    传送门 (https://www.luogu.org/problem/show?pid=2158#sub)


    其实看到SDOI就有一种不太好的预感,,想当年那个猪国杀,,,呵呵,,

    20分暴力

    用二维数组维护每个点能否被选择,之后二维枚举每个点,如果没有被选择就选择,并且用它去遮挡其他所有点

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int maxn = 1000 + 10;
    
    int a[maxn][maxn];
    int n;
    int sum;
    // int ansx[maxn];
    // int ansy[maxn];
    
    void update (int x, int y) {
        int curx = x, cury = y;
        while (curx <= n && cury <= n) {
            curx += (x - 1);
            cury += (y - 1);
            a[curx][cury] = 1;
        }
    }
    
    int main () {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            a[1][i] = 1;
            a[i][1] = 1;
        }
        sum = 2;
        // ansx[1] = 1;
        // ansy[1] = 2;
        // ansx[2] = 2;
        // ansy[2] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 2; j <= n; j++) {
                if (a[i][j] == 0) {
                    a[i][j] = 1;
                    sum++;
                    // ansx[sum] = i;
                    // ansy[sum] = j;
                    update(i, j);
                }
            }
        } 
        printf("%d
    ", sum);
        //for (int i = 1; i <= sum; i++) {
        //     printf("x : %d  y : %d
    ", ansx[i], ansy[i]);
        // }
    
        return 0;
    }
    

    正解:

    其实这道题的正解是打表打出来的,大概把数字取到10左右就能发现某种性质,

    x : 1  y : 2
    x : 2  y : 1
    x : 2  y : 2
    x : 2  y : 3
    x : 2  y : 4
    x : 2  y : 5
    x : 2  y : 6
    x : 2  y : 7
    x : 2  y : 8
    x : 2  y : 9
    x : 2  y : 10
    x : 3  y : 2
    x : 3  y : 4
    x : 3  y : 6
    x : 3  y : 8
    x : 3  y : 10
    x : 4  y : 2
    x : 4  y : 3
    x : 4  y : 5
    x : 4  y : 6
    x : 4  y : 8
    x : 4  y : 9
    x : 5  y : 2
    x : 5  y : 4
    x : 5  y : 6
    x : 5  y : 8
    x : 5  y : 10
    x : 6  y : 2
    x : 6  y : 3
    x : 6  y : 4
    x : 6  y : 5
    x : 6  y : 7
    x : 6  y : 8
    x : 6  y : 9
    x : 6  y : 10
    x : 7  y : 2
    x : 7  y : 6
    x : 7  y : 8
    x : 8  y : 2
    x : 8  y : 3
    x : 8  y : 4
    x : 8  y : 5
    x : 8  y : 6
    x : 8  y : 7
    x : 8  y : 9
    x : 8  y : 10
    x : 9  y : 2
    x : 9  y : 4
    x : 9  y : 6
    x : 9  y : 8
    x : 9  y : 10
    x : 10  y : 2
    x : 10  y : 3
    x : 10  y : 5
    x : 10  y : 6
    x : 10  y : 8
    x : 10  y : 9
    

    由此可见,每个点可取的值与phi[i-1]有关,故使用筛法线性求欧拉函数,之后根据对称性并考虑特殊点,将ans = ans * 2 + 1即为结果

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    const int maxn = 40000 + 100;
    
    int phi[maxn], isprime[maxn], prime[maxn];
    int n;
    int tot = 0;
    long long ans = 0;
    
    int main () {
        scanf("%d", &n);
        phi[1] = 1;
        for (int i = 1; i <= n; i++) isprime[i] = 1;
        for (int i = 2; i <= n; i++) {
            if (isprime[i]) {
                tot++;
                prime[tot] = i;
                phi[i] = i - 1;
            }
            for (int j = 1; j <= tot; j++) {
                if (i * prime[j] > n) break;
                isprime[i * prime[j]] = 0;
                if (i % prime[j] == 0) {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                } else {
                    phi[i * prime[j]] = phi[i] * (prime[j] - 1);
                }
            }
        }
        // for (int i = 1; i <= n; i++) printf("phi[%d] = %d
    ", i, phi[i]);
        for (int i = 2; i <= n; i++) {
            ans = ans + (long long)phi[i-1];
        }
        ans = ans * 2 + 1;
        printf("%lld", ans);
        return 0;
    }
    
    
  • 相关阅读:
    linux查看日志文件内容命令tail、cat、tac、head、echo
    改变自己的128种方法,教你变得更优秀!
    php 23种设计模式
    Swoole消息推送
    PHP 出现 502 解决方案
    【centos7】添加开机启动服务/脚本
    curl 参数配置详解
    i系列标准-互联网周刊
    MySQL 设计与开发规范2
    Cocos Creator webviw网页置顶增加返回键的方法
  • 原文地址:https://www.cnblogs.com/CtsNevermore/p/6023001.html
Copyright © 2011-2022 走看看