zoukankan      html  css  js  c++  java
  • 【*篇】SDOI2008 沙拉公主的困惑

    传送门!

    题目在里...

    题目大意?

    难道不是说的很清楚了么OvO
    求n!中与m!互质的数的个数..

    题目分析.

    显然的数论... 所以就是化式子呗..
    一个很显然的性质就是如果(gcd(a,b)=1),那么(gcd(a+kb,b)=1)...
    而题目中说了(mleqslant n), ∴ (m!|n!)
    于是我们只需要计算(m!)中与(m!)互质的数的个数,然后乘以(frac{n!}{m!})即可..
    我们发现上面加粗的这一坨就是(varphi(m!))嘛...
    所以(ans=varphi(m!)*frac{n!}{m!})
    又有(varphi(x)=x*prod_{i}^{n}(1-frac{1}{p_i})) 其中(p_i)表示x的质因数...
    (m!=1*2*...*m), 所以(m!)的质因数很显然就是不大于(m)的质数...
    然后带入上式约掉(m!)就有了(ans=n!*prod_{i}^{n}frac{p_i-1}{p_i}) (其中(p_ileqslant m)(p_i)为质数)...
    由于多组询问, 而且内存开了256MB不是 所以我们要预处理... 不然会T...
    由于上式, 我们要预处理的东西有:

    • 筛素数(简单欧拉筛)
    • 阶乘(顺着乘一遍取模就行了)
    • 逆元(要递推求出所有数的哦) (所以最好用(O(n))的, 不会的话直接看代码就行了 百度一下一堆详细讲解OvO)
    • (mul_i=prod_{i}^{n}frac{p_i-1}{p_i})这一坨东西...(不大于(m)的质数(p_i)们的((1-frac{1}{p_i}))的乘积...)
      然后处理这一坨的时候也很容易...递推即可.. 显然, 我们有
    1. (i)是质数时, (mul_i=mul_{i-1}*frac{i-1}{i})
    2. 否则(mul_i=mul_{i-1})即可...
      这样就做完了.

    实现代码:

    #include <cstdio>
    typedef long long LL;
    const int X=1e7+3;
    inline int gn(int a=0,char c=0){
        for(;c<48||c>57;c=getchar());
        for(;c>47&&c<58;c=getchar())
            a=a*10+c-48; return a;
    }
    int inv[X],fac[X],eu[X],mul[X],pri[X/10],tot;
    bool notp[X]; int T,R,M,N;
    void prime(){
        notp[1]=1;
        for(int i=2;i<X;++i){
            if(!notp[i])pri[++tot]=i;
            for(int j=1;j<=tot&&i*pri[j]<=1e7;++j){
                notp[i*pri[j]]=1; if(i%pri[j]==0) break;
            }
        }
    }
    void calcinv(){
        inv[1]=1;
        for(int i=2;i<X;++i){
            inv[i]=(LL)(R-R/i)*inv[R%i]%R;
            if(inv[i]<0) inv[i]+=R;
        }
    }
    void calcfac(){
        fac[1]=1;
        for(int i=2;i<X;++i)
            fac[i]=(LL)fac[i-1]*i%R;
    }
    void calcmul(){
        mul[1]=1;
        for(int i=2;i<X;++i)
            if(!notp[i]) mul[i]=(LL)mul[i-1]*(i-1)%R*inv[i]%R;
            else mul[i]=mul[i-1];
    }
    int main(){
        T=gn(),R=gn();
        prime(); calcinv(); calcfac(); calcmul();
        while(T--){
            N=gn(),M=gn();
            printf("%d
    ",(int)((LL)fac[N]*mul[M]%R));
        }
    }
    

    注意事项~

    1. 做乘法的时候要转long long,(当然你要是全用long long算当我没说
    2. 预处理的时候1的值作为边界值给出, 循环要从2开始
    3. 每一步都记得取模
    4. 输出的时候记得换行而不是空格(我是不是暴露了什么←_←

    完结撒花

  • 相关阅读:
    Open source cryptocurrency exchange
    Salted Password Hashing
    95. Unique Binary Search Trees II
    714. Best Time to Buy and Sell Stock with Transaction Fee
    680. Valid Palindrome II
    Java compiler level does not match the version of the installed Java project facet.
    eclipse自动编译
    Exception in thread "main" java.lang.StackOverflowError(栈溢出)
    博客背景美化——动态雪花飘落
    java九九乘法表
  • 原文地址:https://www.cnblogs.com/enzymii/p/8412195.html
Copyright © 2011-2022 走看看