zoukankan      html  css  js  c++  java
  • BZOJ 2111 / Luogu P2606 [ZJOI2010]排列计数

    题意

    称一个1,2,...,N1,2,...,N的排列P1,P2...,PnP_1,P_2...,P_nMagicMagic的,当且仅当2<=i<=N2<=i<=N时,Pi>Pi/2P_i>P_{i/2}. 计算1,2,...N1,2,...N的排列中有多少是MagicMagic的,答案可能很大,只能输出模PP以后的值。

    题解

    这道题最妙的就是把题目转化为求nn个点的小根堆数量。

    然后就随便DP了。

    注意模数可能小于NN,要用lucaslucas定理。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 2000005;
    
    int fac[MAXN], inv[MAXN], mod, n, sz[MAXN];
    
    inline int C(int x, int y) {
    	if(x < y) return 0;
    	if(x < mod && y < mod) return 1ll * fac[x] * inv[y] % mod * inv[x-y] % mod;
    	return 1ll * C(x%mod, y%mod) * C(x/mod, y/mod) % mod;
    }
    
    void dfs1(int i) {
    	if(i > n) return;
    	sz[i] = 1;
    	dfs1(i<<1); sz[i] += sz[i<<1];
    	dfs1(i<<1|1); sz[i] += sz[i<<1|1];
    }
    
    int dfs2(int i) {
    	if(i > n) return 1;
    	int re = C(sz[i]-1, sz[i<<1]);
    	re = 1ll * re * dfs2(i<<1) % mod;
    	re = 1ll * re * dfs2(i<<1|1) % mod;
    	return re;
    }
    
    int main ()
    {
    	scanf("%d%d", &n, &mod);
    	fac[0] = inv[0] = fac[1] = inv[1] = 1;
    	for(int i = 2; i <= n; ++i) inv[i] = 1ll * (mod - mod/i) * inv[mod%i] % mod;
    	for(int i = 2; i <= n; ++i) fac[i] = 1ll * fac[i-1] * i % mod, inv[i] = 1ll * inv[i] * inv[i-1] % mod;
    	dfs1(1);
    	printf("%d
    ", dfs2(1));
    }
    
  • 相关阅读:
    ssh免密登录
    idea搭建flink环境
    idea快捷键列表
    scala对复杂json的处理
    配置三台服务器的时间同步-linux 及 ntp.conf配置文件详解
    91. Reverse Linked List 反转链表
    92. Reverse Linked List II 反转链表 II
    121. Best Time to Buy and Sell Stock 买卖股票的最佳时机
    53. Maximum Subarray最大子序和
    70. Climbing Stairs爬楼梯
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039222.html
Copyright © 2011-2022 走看看