zoukankan      html  css  js  c++  java
  • BZOJ2186: [Sdoi2008]沙拉公主的困惑

    Description

      大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。

    Input

    第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模后面T行,每行一对整数N,M,见题目描述 m<=n

    Output

    共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值

    Sample Input

    1 11
    4 2

    Sample Output

    1

    数据范围:
    对于100%的数据,1 < = N , M < = 10000000

    Solution

    因为保证(m<=n)
    所以有(m!|n!)
    因为(m!)内与(m!)互质的数为(phi(m!))
    所以(ans = phi(m!)*frac{n!}{m!})(相当于把(n!)分成多段,每段(m!)

    [large egin{align*} ans &= phi(m!)*frac{n!}{m!}\ &=frac{n!}{m!}*m!*frac{prod{p[i]-1}}{prod{p[i]}}\ &=n!*frac{prod{(p[i]-1)}}{prod{p[i]}} end{align*}\ ]

    然后直接做就行了

    #include <cstdio>
    #include <iostream>
    #include <bitset>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    int read()
    {
        char x;
        while((x = getchar()) > '9' || x < '0') ;
        int u = x - '0';
        while((x = getchar()) <= '9' && x >= '0') u = (u << 3) + (u << 1) + x - '0';
        return u;
    }
    int buf[105];  
    inline void write(int i) {  
        int p = 0;  
        if(i == 0) p++;  
        else while(i) {  
            buf[p++] = i % 10;  
            i /= 10;  
        }  
        for(int j = p-1; j >= 0; j--) putchar('0' + buf[j]);  
    } 
    
    using namespace std ;
    
    #define N 10000010
    
    int T, mod;
    ll fac[N], inv[N];
    ll ans[N];
    bitset<N> pri;
    // m <= n -> m!|n!
    // 所以 n!中与m!互质的数的个数为 phi(m!)*(n!/m!) 
    
    int main() {
    	pri.set();
        for(int i = 2; i < N; ++i) {
        	if(pri[i])
        		for(int j = i + i; j < N; j += i) pri[j] = 0;
    	}
        
        T = read(); mod = read();
        fac[0] = 1; 
        for(int i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % mod;
        inv[0] = inv[1] = 1; 
        for(int i = 2; i < N; ++i) {
            if(i >= mod) break;
            inv[i] = (mod - mod / i) * inv[mod % i] % mod;
        }
        ans[1] = 1;
        for(int i = 2; i < N; i ++) {
            if(pri[i]) {
                ans[i] = ans[i - 1] * (i - 1) % mod;
                ans[i] = ans[i] * inv[i % mod] % mod;
            } else ans[i] = ans[i - 1];
        }
    	int n, m;
        while(T--) {
            n = read(); m = read();
            ll ANS = fac[n] * ans[m] % mod;
        	write(ANS), putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    Java学习之IO之File类一
    Java学习之二分查找算法
    Java学习之国际化程序
    Java学习之自定义异常
    Java学习之开篇—个人随想
    pl/sql 的 put和put_line区别
    Java中static、final用法
    一个包含所有c++的头文件的头文件
    Codeforces Round #379 (Div. 2)
    hdu-5977 Garden of Eden(树分治)
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10206415.html
Copyright © 2011-2022 走看看