BZOJ1485

BZOJ1485
  • 题目

    BZOJ1485

  • 分析

    可以找规律发现是 C a t l a n Catlan Catlan 数列。。

    还是证明一下:

    性质2: a 1 &lt; a 3 &lt; . . &lt; a 2 i − 1 a_1 &lt; a_3 &lt; ..&lt;a_{2i-1} a1<a3<..<a2i1 , a 2 &lt; a 4 &lt; . . . &lt; a 2 i a_2&lt;a_4&lt;...&lt;a_{2i} a2<a4<...<a2i


    a 1 &lt; a 3 &lt; . . . a 2 i − 1 &lt; a 2 i 可 以 得 出 在 偶 数 位 上 的 数 比 它 左 边 所 有 数 都 要 大 , 换 句 话 说 偶 数 位 上 的 数 大 于 等 于 这 个 偶 数 位 的 下 标 。 由 性 质 2 从 小 到 大 放 数 字 的 时 候 要 尽 量 靠 左 放 假 设 已 经 放 了 1 ∼ x 个 数 , x 1 个 放 在 奇 数 位 上 , x 2 个 放 在 偶 数 位 上 , 则 x 2 &lt; x 1 . 证 明 一 下 : 假 设 x 2 &gt; x 1 , x 2 &gt; x 2 , 由 偶 数 位 上 的 数 大 于 等 于 这 个 偶 数 位 的 下 标 , 最 后 一 个 偶 数 位 下 标 应 该 是 2 × x 2 2 × x 2 &gt; x , 而 只 有 x 个 数 , 所 以 假 设 不 成 立 。 \begin{aligned} &amp; a_1 &lt; a_3 &lt; ... a_{2i-1} &lt; a_{2i} \\ &amp; 可以得出在偶数位上的数比它左边所有数都要大,换句话说偶数位上的数大于等于这个偶数位的下标。\\ &amp; 由性质2从小到大放数字的时候要尽量靠左放 \\ &amp; 假设已经放了1 \sim x 个数,x_1个放在奇数位上,x_2个放在偶数位上,则x_2 &lt; x_1. \\ &amp; 证明一下:\\ &amp; 假设x_2 &gt; x_1, x_2 &gt; \frac{x}{2},由偶数位上的数大于等于这个偶数位的下标,最后一个偶数位下标应该是 2 \times x_2 \\ &amp; 2 \times x_2 &gt; x,而只有x个数,所以假设不成立。 \end{aligned} a1<a3<...a2i1<a2i21xx1x2x2<x1.x2>x1,x2>2x,,2×x22×x2>x,x
    所以得出结论:按从小到大的顺序放到任意一个数 x x x ,都满足放在偶数位上的数字个数小于等于放在奇数位上的数字个数 .

    这很明显是 C a t l a n Catlan Catlan 数。。。

    本题实现还是有点意思。。

    J a v a Java Java 大数超时可能太卡了吧。。。 J a v a Java Java 不知道开了多少时间。。

    C a t l a n Catlan Catlan 数列通项公式用: C 2 n n ( n + 1 ) ! \displaystyle\frac{C_{2n}^{n}}{(n+1)!} (n+1)!C2nn 化简: ∏ i = n + 2 2 n i n ! \displaystyle\frac{\prod_{i = n+2}^{2n}i}{n!} n!i=n+22ni

    模数居然不是质数。。。不好求逆元

    运用智慧

    对分子用唯一分解,分成 p 1 c 1 p 2 c 2 . . . p m c m p_1^{c_1}p_2^{c_2}...p_m^{c_m} p1c1p2c2...pmcm ,分母: p 1 b 1 p 2 b 2 . . . . p m b m p_1^{b_1}p_2^{b_2}....p_m^{b_m} p1b1p2b2....pmbm

    除的话就是: p 1 c 1 − b 1 p 2 c 2 − b 2 . . . p m c m − b m p_1^{c_1-b_1}p_2^{c_2-b_2}...p_m^{c_m-b_m} p1c1b1p2c2b2...pmcmbm , k s m ksm ksm 一下,就可以了。。注意分解的时候要预处理出 1 ∼ 2 n 1\sim 2n 12n 的质数会快很多。。别傻乎乎的直接算。。说的就是我

  • 代码

    const int N = 2e6 + 6;
    int v[N], prime[N];
    int m;
    int c[N];
    void primes(int n) {
    	memset(v, 0, sizeof(v));
    	m = 0;
    	for (int i = 2; i <= n; i++) {
    		if (v[i] == 0) {
    			v[i] = i;
    			prime[++m] = i;
    		}
    		for (int j = 1; j <= m; j++) {
    			if (prime[j] > v[i] || prime[j] > n / i) break;
    			v[i * prime[j]] = prime[j];
    		}
    	}
    }
    void divid(int x, int d)
    {
    	for (int i = 1; i <= m && prime[i] * prime[i] <= x; i++)
    	{
    		if (x % prime[i] == 0)
    		{
    			while (x % prime[i] == 0)
    			{
    				c[prime[i]] += d;
    				x /= prime[i];
    			}
    		}
    	}
    	if (x > 1) c[x] += d;
    }
    ll ksm(ll a, ll b, ll mod)
    {
    	ll ans = 1 % mod;
    	while (b > 0)
    	{
    		if (b & 1) ans = ans * a % mod;
    		b >>= 1;
    		a = a * a % mod;
    	}
    	return ans % mod;
    }
    int main()
    {
    	int n, p;
    	read(n);
    	read(p);
    	primes(n << 1);
    	for (int i = n + 2; i <= (n << 1); i++) divid(i, 1); // 处理分子
    	for (int i = 1; i <= n; i++) divid(i, -1); // 处理分母
    	ll ans = 1;
    	for (int i = 1; i <= m; i++)
    	{
    		if (c[prime[i]]) { 
    			ans = ans * ksm(prime[i], c[prime[i]], p); //累乘
    			ans %= p;
    		}
    	}
    	cout << ans << endl;
    	return 0 ;
    }
    
  • 题型

    C a t l a n Catlan Catlan

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值