hdu 4059 数论+高次方求和+容斥原理

http://acm.hdu.edu.cn/showproblem.php?pid=4059

现场赛中通过率挺高的一道题 但是容斥原理不怎么会。。

参考了http://blog.csdn.net/acm_cxlove/article/details/7434864

1、求逆元   p=1e9+7是素数,所以由 a^(p-1)%p同余于1 可得a%p的逆元为a^(p-2)

2、segma(i^k)都可以通过推导得到求和公式 详见http://blog.csdn.net/acm_cxlove/article/details/7434864

3、容斥原理,还在恶补中  代码写的挺漂亮

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
#include <vector>
using namespace std;
#define ll long long
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)

const int MOD  =  1000000007;
const int N = 10005;
const int M = 10050;
ll n,thr;//thr 30的逆元
vector<int>fac;

bool is[N]; int prm[M];
int getprm(int n){
    int i, j, k = 0;
    int s, e = (int)(sqrt(0.0 + n) + 1);
    memset(is, 1, sizeof(is));
    prm[k++] = 2; is[0] = is[1] = 0;
    for(i = 4; i < n; i += 2) is[i] = 0;
    for(i = 3; i < e; i += 2) if(is[i]) {
            prm[k++] = i;
            for(s = i * 2, j = i * i; j < n; j += s)
                is[j] = 0;
// 因为j是奇数,所以+奇数i后是偶数,不必处理!
        }
    for( ; i < n; i += 2) if(is[i]) prm[k++] = i;
    return k;  // 返回素数的个数
}

ll qmod(ll x,ll t)
{
    ll ret=1,base=x;
    while(t)
    {
        if(t&1)ret=(ret*base)%MOD;
        base=(base*base)%MOD;
        t/=2;
    }
    return ret;
}

ll sum(ll x)
{
    ll ret=1;
    ret=(ret*x)%MOD;
    ret=(ret*(x+1))%MOD;
    ret=(ret*((2*x+1)%MOD))%MOD;
    ret=(((3*x*x)%MOD+(3*x)%MOD-1+MOD)%MOD*ret)%MOD;
    return (ret*thr)%MOD;
}

inline ll four(ll x)
{
    return (((x%MOD)*x%MOD)*x%MOD)*x%MOD;
}

ll dfs(int cur, ll tmp)//容斥原理
{
    ll ret=0,f;
    for(int i=cur;i<fac.size();i++)
    {
        f=fac[i];
        ret=(ret+(sum(tmp/f)*four(f))%MOD)%MOD;
        ret=( (ret-dfs(i+1,tmp/f)*four(f))%MOD+MOD )%MOD;
    }
    return ret%MOD;
}

int main()
{
    //IN("hdu4059.txt");
    int ncase;
    ll s1,s2;
    scanf("%d",&ncase);
    int prmnum=getprm(N-1);
    thr=qmod(30,MOD-2);
    while(ncase--)
    {
        scanf("%I64d",&n);
        //int sn=(int)sqrt(n);
        fac.clear();
        ll tmp=n;
        for(int i=0;i<prmnum && prm[i]<=tmp;i++)
        {
            if(tmp%prm[i] == 0)
            {
                fac.push_back(prm[i]);
                while(tmp%prm[i] == 0)
                    tmp/=prm[i];
            }
        }
            //while(tmp%prm[i] == 0)fac.push_back(prm[i]),tmp/=prm[i];
        if(tmp!=1)fac.push_back(tmp);
        //cout << "FUck= " << sum(n) << endl;
        printf("%I64d\n",( (sum(n)- dfs(0,n)+MOD)%MOD + MOD)%MOD );
    }
    return 0;
}
时间: 2024-10-18 17:32:52

hdu 4059 数论+高次方求和+容斥原理的相关文章

HDU 4059 The Boss on Mars ( 容斥原理)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4059 题意: 给定一个数n求小于n的与n互斥的数的四次方的和. 分析: 我们可以求出从1~n的所有数的四次方的和sum1,然后容斥求出1~n所有与n不互斥的数的四次方的和sum2: ans =sum1 - sum2; 设f(n)表示从1~n的所有数的四次方的和 f(n)=1/30*n*(n+1)(2n+1)(3n^2+3n-1); 推倒如下: (n+1)^5-n^5=5n^4+10n^3+10n^

HDU 4059 The Boss on Mars-矩阵+容斥

错了29遍,终成正果..... 根据题意,很容易的可以想到容斥. 然后的问题就是如何求 sum(n)=1^4+2^4+3^4+....+n^4; 有三种道路: 很显然:1^4+2^4+3^4+....+n^4=(n^5)/5+(n^4)/2+(n^3)/3-n/30: 则1,用java的大数去敲这个的代码. 2,用c++敲,但是用到分数取模,求逆元. 3,用c++敲,但是不用这个公式,用矩阵去构造sum(n). 我用的是第三种.但是第三种有的缺陷,就是时间复杂度有点高. 接下来的问题就是如何优化

hdu 4542 数论 + 约数个数相关 腾讯编程马拉松复赛

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4542 小明系列故事--未知剩余系 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 889    Accepted Submission(s): 207 Problem Description "今有物不知其数,三三数之有二,五五数之有三,七七数之有

HDU 2204 Eddy&#39;s爱好(容斥原理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2204 解题报告:输入一个n让你求出[1,n]范围内有多少个数可以表示成形如m^k的样子. 不详细说了,自己一开始也忽略了三个素数的乘积的乘方的情况. 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6

HDU 1695 GCD 欧拉函数+容斥原理+质因数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:在[a,b]中的x,在[c,d]中的y,求x与y的最大公约数为k的组合有多少.(a=1, a <= b <= 100000, c=1, c <= d <= 100000, 0 <= k <= 100000) 思路:因为x与y的最大公约数为k,所以xx=x/k与yy=y/k一定互质.要从a/k和b/k之中选择互质的数,枚举1~b/k,当选择的yy小于等于a/k时,可以

hdu 1124 数论

题意:求n!中末尾连续0的个数  其实就是2*5的个数 30! 中有5 10 15 20 25 30  是5的倍数有6个   6=30/5; 6/5=1; 这个1 为25 5  10 15 20  25  30 35 40 45 50 55 60  65 70 75 80  85 90 95 100      100/5=20; 25                     50                    75                     100       20/5=4

hdu 3641 数论 二分求符合条件的最小值数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=3641 学到: 1.二分求符合条件的最小值 /*==================================================== 二分查找符合条件的最小值 ======================================================*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <=

HDU 4059 容斥初步练习

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #define LL long long 6 using namespace std; 7 const LL Mod=1000000007; 8 const LL Maxn=60010; 9 LL Factor[35],cnt,n,m,tot,Rev,Kase,Prime[Maxn];

P次方求和 NYOJ 420

1 #include<stdio.h>//P次方求和(420) 2 long long power(int a,int b) 3 { 4 long long t; 5 if(b==0)return 1%10003; 6 if(b==1)return a%10003; 7 t=power(a,b/2); 8 t=t*t; 9 if(b&1)return a*t%10003; 10 else return t%10003; 11 } 12 int main() 13 { 14 int x;