zoukankan      html  css  js  c++  java
  • 题解 P2480 【[SDOI2010]古代猪文】

    题目链接

    Solution [SDOI2010]古代猪文

    题目大意:给定(G),(n),求(G^{sum_{d mid n}C_n^d} ; mod;999911659)

    欧拉定理,卢卡斯定理,EXCRT


    分析:

    我们发现问题的关键在于指数,然后答案可以用快速幂计算

    首先我们观察模数,写个小程序发现(999911659)是个质数,于是我们可以用欧拉定理把指数缩小

    (gcd(a,p)=1),有(a^b equiv a^{b;mod;phi(p)};mod;p)

    如果你(95)的话不妨加一个特判

    好像也可以扩展欧拉定理不过哪儿那么麻烦

    然后我们要求(sum_{d mid n}C_n^d ; mod;999911658)

    (n)的所有约数我们可以(O(sqrt{n}))枚举,不用(O(n))因为约数成对出现

    然后(C_n^d ; mod;999911658)这玩意儿可以扩展卢卡斯定理,但是这个模数比较特殊。我怀疑出题人是精心选取过的

    (999911658=2 imes 3 imes 4679 imes 35617)

    它有(4)个质因子并且指数都为(1)

    我们可以分别对上述(4)个质因子取膜,EXCRT合并即可

    //2 * 3 * 4679 * 35617
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const int maxp = 36000; 
    ll qpow(ll a,ll b,ll mod){
    	a %= mod;
    	ll res = 1,base = a;
    	while(b){
    		if(b & 1)res = (res * base) % mod;
    		base = (base * base) % mod;
    		b >>= 1;
    	}
    	return res;
    }
    ll gcd(ll a,ll b){return !b ? a : gcd(b,a % b);}
    ll lcm(ll a,ll b){return a / gcd(a,b) * b;}
    ll exgcd(ll a,ll b,ll &x,ll &y){
    	if(!b){
    		x = 1,y = 0;
    		return a;
    	}
    	ll res = exgcd(b,a % b,y,x);
    	y -= (a / b) * x;
    	return res;
    }
    ll mul(ll a,ll b,ll p){return (a * b) % p;}
    struct Lucas{
    	ll fac[maxp],inv[maxp],p;
    	inline void init(ll x){
    		p = x,fac[0] = 1,inv[0] = qpow(fac[0],p - 2,p);
    		for(int i = 1;i <= p;i++)
    			fac[i] = (fac[i - 1] * i) % p,inv[i] = qpow(fac[i],p - 2,p);
    	}
    	inline ll C(ll n,ll m){
    		return m > n ? 0 : mul(fac[n],mul(inv[m],inv[n - m],p),p);
    	}
    	inline ll lucas(ll n,ll m){
    		return !m ? 1 : (lucas(n / p,m / p) * C(n % p,m % p)) % p;
    	}
    }lucas[8];
    ll n,base,exp,b[8],m[8] = {0,2,3,4679,35617};
    inline ll excrt(){
    	ll M = m[1],res = b[1];
    	for(int i = 2;i <= 4;i++){
    		ll t,k,s = ((b[i] - res) % m[i] + m[i]) % m[i];
    		ll r = exgcd(M,m[i],t,k);
    		if(s % r)return -1;
    		t = mul(t,s / r,m[i] / r);
    		res += t * M;
    		M = lcm(M,m[i]);
    		res = (res % M + M) % M;
    	}
    	return res;
    }
    int main(){
    	scanf("%lld %lld",&n,&base);
    	if(!(base % 999911659))return printf("0
    "),0;
    	for(int i = 1;i <= 4;i++)lucas[i].init(m[i]);
    	for(int i = 1;i * i <= n;i++)
    		if(!(n % i))
    			for(int k = 1;k <= 4;k++){
    				b[k] += lucas[k].lucas(n,i);
    				if(i != n / i)b[k] += lucas[k].lucas(n,n / i);
    			}
    	exp = excrt();
    	printf("%lld
    ",qpow(base,exp,999911659));
    	return 0;
    }
    
  • 相关阅读:
    C#验证类(使用正则表达式)
    SQL数据库还原语句
    JS键盘或鼠标事件
    列表针对列宽度自动调整显示内容,超长以...缩写结尾
    SQL按照日、周、月、年统计数据 (转自BLEACH的blog)
    SQL利用Case When Then多条件判断
    调用Web服务:请求因HTTP状态401失败:Unauthorized
    IFrame自动适应宽高,去掉空白
    Asp调用WebService事例
    Timer不执行Elapsed事件的解决办法
  • 原文地址:https://www.cnblogs.com/colazcy/p/11687029.html
Copyright © 2011-2022 走看看