zoukankan      html  css  js  c++  java
  • 【BZOJ-4173】数学 欧拉函数 + 关于余数的变换

    4173: 数学

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 306  Solved: 163
    [Submit][Status][Discuss]

    Description

     

    Input

     输入文件的第一行输入两个正整数 。 

    Output

     如题

    Sample Input

    5 6

    Sample Output

    240

    HINT

     N,M<=10^15

    Source

    Solution

    数论好题,开始无从下手,推导后感觉新姿势++

    题目大意:求$varphi(n)*varphi(m)*sum_{kin S(n,m)}varphi(k) mod p$其中$p=998244353$且$S(n,m)=left {n mod k+m mod k>=k ight }$

    首先把式子拆解一下,先看$S(n,m)=left {n mod k+m mod k>=k ight }$:

    不妨设$n=q_{1}*k+r_{1}$,$m=q_{2}*k+r_{2}$

    那么很显然有:$n mod k=r_{1}$,$n / k=q_{1}$,$m mod k=r_{2}$,$m / k=q_{2}$

    那么$S(n,m)=left {n mod k+m mod k>=k ight }$就可以先化成$S(n,m)=left {r_{1}+r_{2}>=k ight }$

    那么根据上述,同样的有:$n+m=(q_{1}+q_{2})*k+(r_{1}+r_{2})$

    很显然$(r_{1}+r_{2})/k<=1$,如果有$r_{1}+r_{2}>=k$,那么$(n+m) mod k=r_{1}+r_{2}-k$,且$(n+m)/k=q_{1}+q_{2}+1$

    这样发现,开始的$S(n,m)=left {n mod k+m mod k>=k ight }$就可以等价为$frac{n+m}{k}-frac{n}{k}-frac{m}{k}=1$

    所以$sum_{kin S(n,m)}varphi(k)$就可以等价成$frac{n+m}{k}sum_{k=1}^{n+m}varphi(k)-frac{n}{k}sum_{k=1}^{n}varphi(k)-frac{m}{k}sum_{k=1}^{m}varphi(k)$

    根据有一个性质$n=sum_{d|n}varphi(d)$那么上述式子可以转化成:$sum_{i=1}^{n+m}-sum_{i=1}^{n}-sum_{i=1}^{m}$

    根据求和公式$frac{n(n-1)}{2}$再变换为$frac{(n+m)(n+m-1)}{2}-frac{n(n-1)}{2}-frac{m(m-1)}{2}$

    化简一下发现$frac{(n+m)(n+m-1)}{2}-frac{n(n-1)}{2}-frac{m(m-1)}{2}=n*m$

    所以最后的答案为$ans=varphi(n)*varphi(m)*n*m$

    那么用$sqrt{n}$的时间复杂度求出$varphi$即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    long long read()
    {
        long long x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define p 998244353
    long long n,m;
    long long phi(long long x)
    {
        long long y=(long long)sqrt(n+0.5);
        long long re=x;
        for(long long i=2; i<=y; i++)
            if(!(x%i))
            {
                re=re/i*(i-1);
                while(!(x%i)) x/=i;
            }
        if(x>1) re=re/x*(x-1);
        return re;
    }
    int main()
    {
        n=read(),m=read();
        long long ans;
        ans=((((phi(n)%p)*(phi(m)%p))%p*(m%p))%p*(n%p))%p;
        printf("%lld
    ",ans);   
        return 0;
    }

    很早以前写的..博客搬家没搬进来...

  • 相关阅读:
    shell test -n -z
    java -d64
    shell export
    topngroupcollector
    stat 查看文件修改时间
    随机30道小学计算题02(修改)
    设计四则运算2程序单元测试用例
    学习进度02
    随机30道小学计算题02
    随机30道小学计算题01
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5426390.html
Copyright © 2011-2022 走看看