• 数论(容斥原理)hdu-4509-The Boss on Mars


    题目链接:

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

    题目大意:

    给一个n,求1~n中与n互质的数的4次方的总和。

    解题思路:

    容斥原理、逆元、公式。

    其实是蛮简单的一道题。囧囧。

    首先必须知道1^4+2^4+...+n^4=n*(n+1)*(2n+1)(3n^2+3n-1)/30. 除以30可以转化成乘以30的逆元,30^(M-2) 由费马小定理很快可以得到。

    先求出1^4+2^4+...+n^4然后减去与n不互质的。  假设n=p1^a1*p2^a2...pn^an  用容斥原理先减去含一个质因数的所有的不超过n的倍数,然后加上含两个质因数的,然后减去含三个质因数的。一个dfs就可以搞定。

    代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #define eps 1e-6
    #define INF 0x1f1f1f1f
    #define PI acos(-1.0)
    #define ll __int64
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #define M 1000000007
    using namespace std;
    
    
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    
    ll pp[10]; //10个就够了
    ll cnt,n,sum,mm;
    
    ll quick(ll a,ll b) //快速幂求 a^b mod M  求30的逆元
    {
       ll res=1;
       while(b)
       {
          if(b&1)
             res=(res*a)%M;
          a=(a*a)%M;
          b>>=1;
       }
       return res;
    }
    ll Four(ll k) //1^4+2^4+...+n^4
    {
       return ((((k*(k+1))%M*(2*k+1))%M*((3*k*k%M+3*k-1)%M))%M*mm)%M;
    }
    void Cal(ll a,ll flag) //求出含有质因数乘积为a的所有的小于n的倍数
    {
       ll k=n/a; //a^4+(2a)^4+(3a)^4+...(k*a)^4=a^4*(1^4+2^4+...+k^4)
       ll res=1;
       for(int i=1;i<=4;i++) //求出a的四次方
          res=(res*a)%M;
       res=(res*Four(k))%M; //求出1~k的四次方和
    
       if(flag&1) //容斥原理
          sum=((sum-res)%M+M)%M;
       else
          sum=(sum+res)%M;
    }
    
    void dfs(ll la,ll pos,ll num) //la表示前面的质因数的乘积,pos表示当前的质因数编号,num表示加还是减
    {
       if(pos>cnt)
          return ;
       for(int i=pos;i<=cnt;i++)
       {
          Cal(la*pp[i],num); //
          dfs(la*pp[i],i+1,num+1);
       }
    }
    int main()
    {
       int t;
    
       scanf("%d",&t);
       mm=quick(30,M-2);  //先求一下逆元
    
       while(t--)
       {
          scanf("%I64d",&n);
          cnt=0;
          ll nn=n;
          sum=Four(n); //求出总的
          for(int i=2;i*i<=nn;i++) //分解质因数 √n的时间复杂度
          {
             if(nn%i==0)
             {
                pp[++cnt]=i;
                while(nn%i==0)
                   nn/=i;
             }
          }
          if(nn!=1)
             pp[++cnt]=nn;
          dfs(1,1,1);
          printf("%I64d
    ",sum);
       }
       return 0;
    }
    
    



  • 相关阅读:
    从马琳决赛被翻盘想到的
    C语言中的位运算
    瑞星杀毒软件所有监控已禁用!
    回来了,重新开始
    使用 javascript 标记高亮关键词
    我的webgis客户端引擎AIMap
    RPM 命令大全
    终结IE6下背景图片闪烁问题
    linux下挂载硬盘光驱和U盘
    在JavaScript中实现命名空间
  • 原文地址:https://www.cnblogs.com/james1207/p/3297152.html
Copyright © 2020-2023  润新知