zoukankan      html  css  js  c++  java
  • zoj 3547 The Boss on Mars 第36届ACM大连预选赛I题

    以下转载于:

    http://blog.csdn.net/xieshimao/article/details/6840731

    数论题!

    求与N不互质的数的K次方(K=4),反过来想若知道与N互质的K次方和,那所求就容易多了哦。

    观察到与n互质的数的性质

    比如12=2*2*3

    那么与12不互质的数就有2,3,4,6,8,9,10,12

    其实就是2的所有倍数,以及3的所有倍数

    所以可以先求一个1到12的所有数的四次方和。这个有公式:

    n*(n+1)*(2*n+1)*(3*n*n+3*n-1)/30

    注意对与除以30可以看成是乘以30的逆元(对于1000000007的逆元)。

    求的所有的四次方和之后当然要减去那些不互质的数的四次方

    也就是说分别剪去了2和3的倍数的四次方,注意这里2和3的公倍数被多减去了,所以要加回来

    所以容斥原理也要用

    /*
    * zoj3547.c
    *
    * Created on: 2011-10-3
    * Author: bjfuwangzhu
    */

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #define LL long long
    #define nmod 1000000007
    #define nmax 10010
    #define nnum 1500
    int prime[nnum], flag[nmax], pfactor[nnum];
    int plen, pflen;
    LL inverse, x, y;
    void extend_gcd(LL a, LL b) {
    if (b == 0) {
    x = 1, y = 0;
    return;
    }
    extend_gcd(b, a % b);
    LL tx = x;
    x = y, y = tx - a / b * y;
    }
    void init() {
    int i, j;
    memset(flag, -1, sizeof(flag));
    for (i = 2, plen = 0; i < nmax; i++) {
    if (flag[i]) {
    prime[plen++] = i;
    }
    for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) {
    flag[i * prime[j]] = 0;
    if (i % prime[j] == 0) {
    break;
    }
    }
    }
    extend_gcd(30, nmod);
    inverse = (x % nmod + nmod) % nmod;
    }
    LL getSumPow(int n) {
    LL res, temp;
    res = 1;
    res = res * n % nmod;
    res = res * (n + 1) % nmod;
    res = res * (n * 2 + 1) % nmod;
    temp = (LL) n;
    temp = ((temp * temp % nmod * 3 + temp * 3 % nmod - 1) % nmod + nmod) % nmod;
    res = res * temp % nmod;
    res = res * inverse % nmod;
    return res;
    }
    LL getPow(int n) {
    LL res;
    res = (LL) n;
    res = res * res % nmod * res % nmod * res % nmod;
    return res;
    }
    LL dfs(int start, int n) {
    LL res;
    int i, temp;
    for (i = start, res = 0; i < pflen; i++) {
    temp = pfactor[i];
    res = (res + getSumPow(n / temp) * getPow(temp) % nmod) % nmod;
    res = ((res - dfs(i + 1, n / temp) * getPow(temp) % nmod) % nmod + nmod)
    % nmod;
    }
    return res;
    }
    int main() {
    #ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
    #endif
    int t, n, N, i, te;
    LL res, temp;
    init();
    while (~scanf("%d", &t)) {
    while (t--) {
    scanf("%d", &n);
    te = (int) sqrt(n * 1.0);
    N = n;
    for (i = 0, pflen = 0; (i < plen) && (prime[i] <= te); i++) {
    if (n % prime[i] == 0) {
    pfactor[pflen++] = prime[i];
    while (n % prime[i] == 0) {
    n /= prime[i];
    }
    }
    }
    if (n > 1) {
    pfactor[pflen++] = n;
    }
    if (n == N) {
    printf("%lld\n", getSumPow(n - 1));
    continue;
    }
    temp = dfs(0, N);
    res = ((getSumPow(N) - temp) % nmod + nmod) % nmod;
    printf("%lld\n", res);
    }
    }
    return 0;
    }

     以下转载于:

    http://hi.baidu.com/tomspirit/blog/item/6b41263b4ef927ef3b87cecf.html

    /*题意:找出比n小且与n互质的数的4次方和4: sum=1+3*3*3*3=82解法:
    * 容斥定理+状态压缩枚举
    * 比如12:sum = Sum(1^4+...12^4)%MOD - (所有非互质数的4次方和)%MOD
    * 求解Sum(1^4+...+12^4)有公式:1/30*n*(n+1)(2n+1)(3n^2+3n-1),
    * 因为式子中有除,取余扩展欧几里得来做。现在的问题是所有非互质数的4次方和。
    * 可以先求12的素因子:2,3。在非互质数中,
    * ①含2素因子的数为2,4,6,8,10;含3素因子的数为3,6,9,12
    * ②含2,3的数为6,12可以看出非互质数 = ① - ②;
    * 满足容斥定理。对于2(含2因子)分别是2,4,6,8,10,12
    * ,转化为题意,2^4+4^4+6^4+8^4+10^4+12^4 = 2^4*(1^4+2^4+3^4+4^4+5^4+6^4)
    * 这样就可以利用上面的公式求解,但是这只是一种情况。我们可以用状态压缩来枚举所有的情况。
    * 对于12,有4中情况,全不选,只选2,只选3和2,3都选,
    * 那么相对于的和为0*(0),2^4(1^4+...+6^4),3^4(1^4+...+4^4),6^4(1^4+...+2^4)
    * 这样才把所有的非互质数的4次方和找到,并利用容斥定理(奇数个素因子为+,偶数个素因子为-),
    * 答案就出来了。
    */
    #include<stdio.h>
    #include<cstring>
    #include<vector>
    #include <map>
    #include<iostream>
    using namespace std;
    const long long MOD = 1000000007;
    const int N = 10010;
    vector<long long> a;
    bool f[N];
    long long prim[N];
    void Extend_euclid(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {
    x = 1;
    y = 0;
    return;
    }
    long long tx, ty;
    Extend_euclid(b, a % b, tx, ty);
    x = ty;
    y = tx - a / b * x;
    }
    void getPrime() {
    long long i, j;
    memset(f, 1, sizeof(f));
    for (i = 2; i * i <= N; i++)
    if (f[i])
    for (j = i * i; j <= N; j += i)
    f[j] = 0;
    f[1] = 0;
    long long pt = 0;
    for (i = 2; i <= N; i++)
    if (f[i])
    prim[pt++] = i;
    }
    long long getCnt(long long nn) {
    long long res = 0, i;
    for (i = 0; prim[i] * prim[i] <= nn; ++i) {
    if (nn % prim[i] == 0) {
    a.push_back(prim[i]);
    nn /= prim[i];
    while (nn % prim[i] == 0) {
    nn /= prim[i];
    }
    if (nn == 1)
    break;
    }
    }
    if (nn > 1)
    a.push_back(nn);
    return a.size();
    }
    long long difNum, n, sum;
    bool bit[10];
    long long pow4(long long aa) {
    return aa * aa % MOD * aa % MOD * aa % MOD;
    }
    int main() {
    long long t, x, y, len, nn;
    int i, j;
    getPrime();
    Extend_euclid(30, MOD, x, y);
    x = (x % MOD + MOD) % MOD;
    scanf("%lld", &t);
    while (t--) {
    a.clear();
    scanf("%lld", &n);
    if (n == 1) {
    printf("0\n");
    continue;
    }
    nn = n;
    sum = nn * (nn + 1) % MOD * (2 * nn % MOD + 1) % MOD
    * (nn * nn % MOD * 3 % MOD + 3 * nn % MOD - 1) % MOD * x % MOD;
    difNum = getCnt(n);
    long long Limit = 1 << difNum;
    for (i = 0; i < Limit; ++i) {
    long long sum1 = 1, cnt = 0;
    for (j = 0; j < difNum; ++j) {
    if ((1 << j) & i) {
    sum1 *= a[j];
    ++cnt;
    }
    }
    if (cnt)
    nn = n / sum1;
    else
    nn = 0;
    if (cnt & 1)
    sum = (sum
    - pow4(sum1)
    * (nn * (nn + 1) % MOD * (2 * nn % MOD + 1)
    % MOD
    * (nn * nn % MOD * 3 % MOD
    + 3 * nn % MOD - 1) % MOD * x
    % MOD) % MOD + MOD) % MOD;
    else
    sum = (sum
    + pow4(sum1)
    * (nn * (nn + 1) % MOD * (2 * nn % MOD + 1)
    % MOD
    * (nn * nn % MOD * 3 % MOD
    + 3 * nn % MOD - 1) % MOD * x
    % MOD) % MOD + MOD) % MOD;
    }
    printf("%lld\n", sum);
    }
    return 0;
    }


     

  • 相关阅读:
    java 面向对象(十八):包装类的使用
    java 面向对象(十七):单元测试方法
    rxjava2学习
    多线程-wait(),notify(),notifyAll()
    多线程-Thread.join()的运用
    66. Plus One
    理解Android View的事件传递机制
    78. Subsets
    程序员学习与成长的方法(转发)
    android查询天气demo,基于mvp+kotlin+rxjava2+retrofit2
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/2198527.html
Copyright © 2011-2022 走看看