zoukankan      html  css  js  c++  java
  • hdu 1695 一道综合性很强的数论题

    这题想了好久,代码也打了好久。挺不错的一道数论题。

    题目是要求两个集合(1...b, 1...d)中有多少对数的最大公约数为K,此问题等价于求两个集合(1...b/k,1...d/k)中有多少对数互质。

    不妨设b<d,则题目可以分为两部分求解,即:

    ①(1...b)与(1...b)中有多少对数互质

    ②(1...b)与(b+1...d)中有多少对数互质

    问题1就是欧拉函数的应用,就不详细说了。

    对于问题2,直接求不好求,我们倒过来想。对于(b+1...d)中的每一个y,要想知道(1...b)中有多少数与它互质,我们只需要知道多少个数与它不互质即可。而两个数不互质就意味着它们有公因子。对于每一个y的因子f,都能确定地知道(1...b)中有多少个数含有因子f,用容斥原理算一下,就能知道(1...b)中有多少个数与y互质了。枚举一下y即可解决问题②了。

    /*
    * hdu1695/win.cpp
    * Created on: 2011-12-11
    * Author : ben
    */
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
    #include <functional>
    #include <numeric>
    #include <cctype>
    using namespace std;
    const int MAXN = 100005;
    const int MAXSQRN = 500;
    typedef long long I64;
    int phi[MAXN], facts[MAXSQRN], prime[MAXSQRN], primenum;

    void initprime() {
    primenum = 3;
    prime[0] = 2;
    prime[1] = 3;
    prime[2] = 5;
    for (int i = 6; i < MAXSQRN; i++) {
    int j = 2;
    for (; j < i; j++) {
    if (i % j == 0) {
    break;
    }
    }
    if (j == i) {
    prime[primenum++] = i;
    }
    }
    }

    inline int getFacts(int y) {
    int I = 0;
    for (int i = 0; i < primenum; i++) {
    if (y <= 1) {
    break;
    }
    if (y % prime[i] == 0) {
    facts[I++] = prime[i];
    while (y % prime[i] == 0) {
    y /= prime[i];
    }
    }
    }
    if(y > 1) {
    facts[I++] = y;
    }
    return I;
    }

    void initphi() {
    int i, j;
    for (i = 1; i <= MAXN; i++) {
    phi[i] = i;
    }
    for (i = 2; i <= MAXN; i += 2) {
    phi[i] /= 2;
    }
    for (i = 3; i <= MAXN; i += 2) {
    if (phi[i] == i) {
    for (j = i; j <= MAXN; j += i) {
    phi[j] = phi[j] / i * (i - 1);
    }
    }
    }
    }

    I64 thesame(int end) {
    I64 ret = 1;
    for (int i = end; i > 1; i--) {
    ret += phi[i];
    }
    return ret;
    }

    I64 dfs(int n, int start, int I) {
    I64 res = 0;
    int i;
    for (i = start; i < I; i++) {
    res += n / facts[i] - dfs(n / facts[i], i + 1, I);
    }
    return res;
    }

    I64 thediff(int b, int d) {
    I64 ret = 0;
    for (int y = b + 1; y <= d; y++) {
    int I = getFacts(y);
    //容斥原理
    ret += b - dfs(b, 0, I);
    }
    return ret;
    }

    int main() {
    #ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
    #endif
    int T, b, d, k, t;
    I64 ans;
    initphi();
    initprime();
    scanf("%d", &T);
    for (t = 1; t <= T; t++) {
    printf("Case %d: ", t);
    scanf(" 1 %d 1 %d %d", &b, &d, &k);
    if (b < k || d < k || k == 0) {
    puts("0");
    continue;
    }
    b /= k;
    d /= k;
    if (b > d) {
    b = b ^ d;
    d = b ^ d;
    b = b ^ d;
    }
    ans = thesame(b);
    ans += thediff(b, d);
    printf("%I64d\n", ans);
    }
    return 0;
    }



  • 相关阅读:
    Spring知识整理
    业务开发(四)—— 服务器
    TCP/IP协议知识整理
    XSS
    Java并发编程(一) —— 线程
    业务开发(三)—— 前端
    Effective Java——(一)创建和销毁对象
    Java编程思想——异常
    Git使用
    网络基础(一)
  • 原文地址:https://www.cnblogs.com/moonbay/p/2283929.html
Copyright © 2011-2022 走看看