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

    题目链接:

    链接

    题目大意:

    求:

    [m^{sum_{d|n}C_{n}^{d}}mod 999911659 ]

    正文:

    这种指数一坨式子外面还套个模的一般考虑欧拉定理的推论或扩展欧拉定理。这个用扩展欧拉定理明显搞不了,就考虑用欧拉定理的推论。

    [m^{sum_{d|n}C_{n}^{d}}equiv m^{sum_{d|n}C_{n}^{d}mod999911658}pmod{999911659} ]

    还是难搞啊这指数一坨。但是我们发现里面有个组合数,这提示了我们可以 Lucas 定理优化,但是这里面的这个模数这么大一坨,还不如不用,所以考虑拆这个模数。在尝试的过程中你可能会试着将 (999911658) 分解质因数,分成了 (2,3,4679,35617) 四个质数。这么小,这么少,满足了我们利用 Lucas。但是怎么将它们重新拼起来才是关键。因为只有四个,很少,所以可以考虑用中国剩余定理:

    [left{egin{matrix} xequiv a_1&quadpmod{2}\ xequiv a_2&quadpmod{3}\ xequiv a_3&quadpmod{4679}\ xequiv a_4&quadpmod{35617} end{matrix} ight.]

    其中 (a_i) 就是要利用 Lucas 求出来的 (sum_{d|n}C_{n}^{d}) 模各质数得到的数。那么最后我们通过 CRT 求得 (x),代入回原式: (m^x)

    代码:

    ll M = 999911659ll, ans;
    ll m_[5] = {0, 2ll, 3ll, 4679ll, 35617ll}, a[5];
    ll prod[N];
    
    void init(ll p)
    {
    	prod[0] = 1;
    	for (register int i = 1; i <= p + 10; i++)
    		prod[i] = (prod[i - 1] * i) % p;
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y)
    {
    	if(b == 0)
    	{
    		x = 1, y = 0;
    		return a;
    	}
    	int gcd = exgcd(b, a % b, y, x);
    	y -= a / b * x;
    	return gcd;
    }
    
    ll qpow(ll a, ll b, ll p)
    {
        a %= p;
    	ll ans = 1;
    	for(; b; b >>= 1, a = a * a % p)
    		if(b & 1)
    			ans = ans * a % p;
        return ans;
    }
    ll C(ll n, ll m, ll p)
    {
        if(m > n)return 0;
        if(n == 0) return 1;
        return ((prod[n] * qpow(prod[m], p - 2, p)) % p * qpow(prod[n - m], p - 2, p) % p);
    }
    
    ll Lucas(ll n, ll m, ll p)
    {
    	if(!m) return 1;
    	return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
    }
    
    int main()
    {
    	scanf ("%d%d", &n, &m);
    	if (m % M == 0) {puts("0"); return 0;}    // 特判 m 是 999911659 因数
    	for (int i = 1; i <= 4; i++)
    	{
    		init(m_[i]);
    		for (int j = 1; j * j <= n; j++)
    		{
    			if(n % j) continue;
    			(a[i] += Lucas(n, j, m_[i])) %= m_[i];
    			if(j * j == n) continue;
    			(a[i] += Lucas(n, n / j, m_[i])) %= m_[i];
    		}
    	}
    	for (int i = 1; i <= 4; i++)
    	{
    		ll t = 0, y; 
    		exgcd(M / m_[i], m_[i], t, y);
    		ans += a[i] * (M / m_[i]) * (t < 0? t + m_[i]: t);
    	}
    	printf("%lld", qpow(m, ans, M));
        return 0;
    }
    
  • 相关阅读:
    使用定时器实现获取手机验证码倒计时
    搜索历史管理
    利用vue和jQuery实现中国主要城市搜索与选择
    使用vue、jQuery生成带有logo的二维码
    使用vue-cli脚手架搭建Vue项目
    postcss-px-to-viewport
    git命令操作篇
    小程序中live-player
    对于常用数组的方法总结
    css的加载中动画
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14117416.html
Copyright © 2011-2022 走看看