zoukankan      html  css  js  c++  java
  • P2155 [SDOI2008]沙拉公主的困惑

    题面

    题目可简化为求:

    [displaystylesum_{i=1}^{n!}{[gcd(i,m!)=1]}(1到n!中,所有与m!互质的数的个数) ]

    如何求解:

    首先假设有(gcd(a,b) = 1),则一定有(gcd(a+b,b)=1)

    所以考虑把(n!)分为(frac{n!}{m!})块,其中(m leq n),所以(n!) mod (m!) 一定等于(0),即我们分出的一定是整数块。

    而且其中每一块中与(m!)互质的数的个数一定是相等的。

    此时我们的式子为:

    [frac{n!}{m!} imesdisplaystylesum_{i=1}^{m!}[gcd(i,m!)=1] ]

    其中

    [displaystylesum_{i=1}^{m!}[gcd(i,m!)=1] ]

    等等,是不是看着有点眼熟?小于等于(m!)的正整数中与(m!)互质的数的数目...不就是欧拉函数的定义吗?

    那这不就是(varphi(m!))吗?

    于是我们的式子就可以完美的变为:

    [frac{n!}{m!} imesvarphi(m!) ]

    因为求(varphi(i))的公式为:

    [varphi(i)=i imesfrac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x}(p为i的所有质因数) ]

    (varphi(i))换为(varphi(m!))代进(frac{n!}{m!} imesvarphi(m!))去展开:

    [frac{n!}{m!} imesvarphi(m!)=frac{n!}{m!} imes m! imesfrac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x} ]

    于是我们的式子就可以化简为:

    [n! imesfrac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x} ]

    注意此时(p)(m!)的所有质因数。

    那么我们的问题就转化为求:

    [n! imesfrac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x} ]

    (n!)好求,对于(frac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x})我们线性求出逆元即容易求出。

    线性预处理出来(1)(maxn)的所有(i!)(frac{p_1-1}{p_1} imes... imesfrac{p_x-1}{p_x})即可(O(1))的询问。

    时间复杂度为(O(1e7+t))

    由蒟蒻代码自带大常数+某谷评测机不稳定,有时候能过有时候不能过,开了(O_2)稳过。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    template<typename temp>void read(temp &x){
    	x = 0;temp f = 1;char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') and (f = -1);
    	for(x = ch^48; isdigit(ch = getchar()); x = (x<<1)+(x<<3)+(ch^48));
    	return (void)(x *= f);
    }
    template <typename temp, typename ...Args>void read(temp& a, Args& ...args){read(a), read(args...);}
    
    const int maxn = 1e7+10;
    
    int t, mod, n, m, cnt, prime[maxn];
    long long inv[maxn], fac[maxn], fi[maxn];
    bool is_prime[maxn];
    
    void memset_mine(){ 
    	fac[0] = fac[1] = inv[0] = inv[1] = fi[0] = fi[1] = 1;
    	for(int i = 2; i <= maxn; i ++){
    		fac[i] = (fac[i-1]*i)%mod, inv[i] = mod-mod/i*inv[mod%i]%mod;
    		fi[i] = fi[i-1];
    		if(!is_prime[i]) prime[++cnt] = i, fi[i] = (fi[i]%mod*(i-1)%mod*inv[i]%mod)%mod;
    		for(int j = 1; j <= cnt and i*prime[j] <= maxn; j ++){
    			is_prime[i*prime[j]] = 1;
    			if(!(i%prime[j])) break;
    		}
    	}
    }
    
    signed main(){
    	read(t, mod);
    	memset_mine();
    	while(t --){
    		read(n, m);
    		printf("%lld
    ", fac[n]%mod*fi[m]%mod);
    	}
    	return 0;
    }
    

    没啦qwq。

  • 相关阅读:
    核心编程笔记8——用户模式下的线程同步
    核心编程随笔7——线程调度和优先级
    深入浅出mfc随笔——MFc程序的生死因果
    opengl
    核心编程6——线程
    深入浅出mfc学习笔记——六大关键技术之仿真_运行时和动态创建
    深入浅出mfc学习笔记——六大关键技术仿真_Persistence(永久保存)
    Gdi+编程
    深入浅出mfc学习笔记1
    file open等待事件
  • 原文地址:https://www.cnblogs.com/Vanyun/p/13492669.html
Copyright © 2011-2022 走看看