首页 > 其他分享 >P3200 [HNOI2009] 有趣的数列

P3200 [HNOI2009] 有趣的数列

时间:2024-08-06 21:18:25浏览次数:14  
标签:cnt 数列 奇数 int 偶数 ff P3200 HNOI2009 mod

哇,太恶心了

思路

首先我们将题意简化,简化后为对于任意一个偶数位所填数必然大于等于自己的下标,那么考虑填数,如果填的偶数比奇数多,那么此时要么填尽偶数后失败,或者下一个位置填奇数就炸,比如偶数刚好多一个,那么必然有一个偶数放在了奇数位,那么本来下一个要填的偶数往前移了一个,导致接下来只能继续填偶数,然后就失败了,所以我们的到结论,任何时候都要保证偶数个数比奇数个数少,所以可以将其转化为卡特兰数,然后一看数据 \(p\) 可为合数,直接寄

code

#include <iostream>

using namespace std;

const int MaxN = 2e6 + 10;

struct math {
  int qpow(int a, int b, int p) {
    int res = 1;
    for (int i = 1; i <= b; i <<= 1) {
      (b & i) && (res = 1ll * res * a % p);
      a = 1ll * a * a % p;
    }
    return res;
  }

  int exgcd(int a, int b, int &x, int &y) {
    if (!b) return x = 1, y = 0, a;
    int g = exgcd(b, a % b, y, x);
    return y = (y - (a / b * x)), g;
  }

  int inv(int x, int p) {
    int b, y;
    exgcd(x, p, b, y);
    return (b % p + p) % p;
  }

  int f(int x, int p, int mod) {
    if (!x) return 1;
    int res = 1;
    for (int i = 1; i <= mod; i++) {
      (i % p) && (res = 1ll * res * i % mod);
    }
    res = qpow(res, x / mod, mod);
    for (int i = 1; i <= x % mod; i++) {
      (i % p) && (res = 1ll * res * i % mod);
    }
    return 1ll * res * f(x / p, p, mod) % mod;
  }

  int CRT(int k, int a[], int r[]) {
    int n = 1, res = 0;
    for (int i = 1; i <= k; i++) n *= r[i];
    for (int i = 1; i <= k; i++) {
      int m = n / r[i];
      res = (res + 1ll * a[i] * m % n * inv(m, r[i]) % n) % n;
    }
    return res;
  }

  bool vis[MaxN];
  int p[MaxN], tot;
  void OLS() {
    for (int i = 2; i < MaxN; i++) {
      if (!vis[i]) p[++tot] = i;
      for (int j = 1; j <= tot && 1ll * p[j] * i < MaxN; j++) {
        vis[p[j] * i] = 1;
        if (i % p[j] == 0) break;
      }
    }
  }

  int get_ans(int n, int m, int p, int mod) {
    int cnt = 0;
    for (int i = n; i; i /= p) cnt += i / p;
    for (int i = m; i; i /= p) cnt -= i / p;
    for (int i = n - m; i; i /= p) cnt -= i / p;
    return 1ll * qpow(p, cnt, mod) * f(n, p, mod) % mod * inv(f(m, p, mod), mod) % mod * inv(f(n - m, p, mod), mod) % mod;
  }

  int a[MaxN], cp[MaxN], mp[MaxN], ff[MaxN], cnt;

  void breakdown(int mod) {
    cnt = 0;
    for (int i = 1; 1ll * p[i] * p[i] <= mod; i++) {
      if (mod % p[i] == 0) {
        for (mp[++cnt] = 1, cp[cnt] = p[i]; mod % p[i] == 0; mp[cnt] *= p[i], mod /= p[i]) {
        }
      }
    }
    (mod > 1) && (mp[++cnt] = mod, cp[cnt] = mod);
    if (cnt == 1) {
      for (int i = 1; i < MaxN; i++) {
        ff[i] = 1ll * ff[i - 1] * i % mod;
      }
    }
  }

  int exLucas(int n, int m, int mod) {
    if (n < m) return 0;
    if (cnt == 1) {  // 大质数去死吧!
      return 1ll * ff[n] * qpow(ff[m], mod - 2, mod) % mod * qpow(ff[n - m], mod - 2, mod) % mod;
    }
    for (int i = 1; i <= cnt; i++) {
      a[i] = get_ans(n, m, cp[i], mp[i]);
    }
    return CRT(cnt, a, mp);
  }

  math() {
    OLS(), ff[0] = 1;
  }
} st;

int n, mod;

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> mod;
  st.breakdown(mod);
  cout << ((st.exLucas(n + n, n, mod) - st.exLucas(n + n, n - 1, mod)) % mod + mod) % mod << '\n';
  return 0;
}

标签:cnt,数列,奇数,int,偶数,ff,P3200,HNOI2009,mod
From: https://www.cnblogs.com/ybtarr/p/18345982

相关文章

  • PHP中如何实现函数的可变参数列表
    在PHP中,实现函数的可变参数列表主要有两种方式:使用func_get_args()函数和使用可变数量的参数(通过...操作符,自PHP5.6.0起引入)。1.使用func_get_args()函数func_get_args()函数用于获取传递给函数的参数列表,并作为一个数组返回。这种方式不需要在函数定义时明确指定参数的数......
  • 5***斐波那契兔子数列
    题目:古典问题(兔子生崽):有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(输出前40个月即可)详解:首先这个输出的值就是斐波那契数列:1,1,2,3,5,8,13,21....,重要特点,也是解题关键是:    每一......
  • 数列区间最大值(ST表)
    预处理部分\[\max(a[i,i+2^k-1])=\max\left\{\begin{aligned}\max&(a[i,i+2^{k-1}-1])\\\max&(a[i+2^{k-1},i+2^{k-1}+2^{k-1}-1])\end{aligned}\right.=\left\{\begin{aligned}\max&(a[i,i+2^{k-1}-1])\\\max&(a[i+2^{k-1},i+2^k-......
  • 数据结构——数列分块 学习笔记
    数据结构——数列分块学习笔记下面部分代码使用,usingll=longlong;#defineintll基础思想问题引入问题:实现区间加;区间求和。基本结构引用经典东西,我们考虑构造一个结构,形如,那么,结论是,复杂度证明为什么块长一般是\(\sqrtn\)呢?我们假设构造的块长是\(......
  • 探秘斐波那契数列:如何在0.02毫秒内计算21亿
    针对斐波那契数列算法进行详细介绍和优化,从最简单的递归方法到更高效的迭代、缓存、动态规划、公式推导和矩阵解法,最终达到了时间复杂度为O(logn)的快速幂矩阵解法来感受算法的神奇之处,最后可以看到如何实现在输入n=2100000000(21亿)时仅耗时0.02毫秒的最佳效果。一、回顾斐波......
  • 极限性能:21亿斐波那契数列在0.02毫秒内计算完成
    针对斐波那契数列算法进行详细介绍和优化,从最简单的递归方法到更高效的迭代、缓存、动态规划、公式推导和矩阵解法,最终达到了时间复杂度为O(logn)的快速幂矩阵解法来感受算法的神奇之处,最后可以看到如何实现在输入n=2100000000(21亿)时仅耗时0.02毫秒的最佳效果。一、回顾斐波......
  • 代码随想录day32 || 509斐波那契数列 70爬楼梯 746使用最小花费爬楼梯
    509斐波那契数列力扣题目链接题目描述:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:F(0)=0,F(1) =1F(n)=F(n-1)+F(n-2),其中n>1给定 n ,请计算 F(n) 。代码1......
  • 单峰数列
    用线段树维护原序列对应的差分数组,可以把区间修改简化为单点修改点击查看代码#include<bits/stdc++.h>usingnamespacestd;inta[100005],n;intread1(){ charcc=getchar(); while(!(cc>=48&&cc<=57)) { if(cc=='-') { break; } cc=getchar(); } bool......
  • 航电第三场(单峰数列)
    单峰数列题意对于一个整数数列,如果其先严格递增,然后在某一点后严格递减,我们称这个数列为单峰数列(严格递增和严格递减的部分均要是非空)。给定长度为n的整数数列\(a_1,a_2,…,a_n\),请你支持q次操作:1lrx:将\(a_l,a_{l+1},…,a_r\)的每个数加x。2lr:判断\(a_l,a_{l......
  • 优美子数列2 题解
    题目id:8628题目描述数学家小\(Q\)得到了一个长度为\(N\)的数列\(a_n\)。小\(Q\)的幸运数字是\(k\),所以他认为,若一个子数列\(a_l,a_{l+1},...,a_r\)的和为\(k\)的倍数,则该子数列是优美子数列。小\(Q\)现在想考考你,\(a_n\)里有多少个优美子数列呢?前置知识前缀和、桶解题思路......