zoukankan      html  css  js  c++  java
  • [BZOJ2655]calc

    [BZOJ2655]calc

    试题描述

    一个序列 (a_1, cdots , a_n) 是合法的,当且仅当:

    长度为给定的 (n)

    (a_1, cdots , a_n) 都是 ([1,A]) 中的整数。

    (a_1, cdots , a_n) 互不相等。

    一个序列的值定义为它里面所有数的乘积,即 (a_1a_2 cdots a_n)

    求所有不同合法序列的值的和。

    两个序列不同当且仅当他们任意一位不一样。

    输出答案对一个数 (mod) 取余的结果。

    输入

    一行 (3) 个数,(A)(n)(mod)。意义为上面所说的。

    输出

    一行结果。

    输入示例

    9 7 10007
    

    输出示例

    3611
    

    数据规模及约定

    (0: A le 10,n le 10)

    (1 sim 3: A le 1000,n le20).

    (4 sim 9: A le 10^9,n le 20)

    (10 sim 19: A le 10^9,n le 500)

    全部:(mod le 10^9),并且 (mod) 为素数,(mod>A>n+1)

    题解

    (f(i, j)) 表示 ([1, i]) 中的数取 (j) 个的所有方案的乘积总和,那么转移如下

    [f(i, j) = f(i-1, j-1) cdot i cdot j + f(i-1, j) ]

    边界条件是 (f(i, i) = (i!)^2, f(a, b) = 0 (a > b)),那么我们可以归纳地用上面的递推式证明 (f(i, j)) 可以表示为一个关于 (i)(2j) 次多项式。首先 (f(i, i)) 就是 (2i) 次多项式,然后那个转移中 (f(i-1, j-1) cdot i cdot j)(2j - 1) 次的,(f(i-1, j))(2j) 次的,两个相加就是 (2j) 次的。

    于是我们 dp 出较小的值,然后拉格朗日插值一下就能得到 (f(A, n)) 关于 (A) 的多项式了,从而得到答案。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
    #define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 510
    #define LL long long
    
    int Arrange, n, MOD, f[maxn*3][maxn], inv[maxn*3];
    
    int X[maxn<<1], Y[maxn<<1];
    int GetPoly(int N, int x) {
    	int ans = 0;
    	rep(i, 1, N) {
    		int sum = Y[i];
    		rep(j, 1, N) if(i != j) {
    			sum = (LL)sum * (x - X[j]) % MOD * inv[abs(X[i]-X[j])] % MOD;
    			if(sum < 0) sum += MOD;
    			if(X[i] < X[j] && sum) sum = MOD - sum;
    		}
    		ans += sum;
    		if(ans >= MOD) ans -= MOD;
    	}
    	return ans;
    }
    
    int main() {
    	Arrange = read(); n = read(); MOD = read();
    	
    	int lim = min(Arrange, n * 3 + 1);
    	rep(i, 0, lim) f[i][0] = 1;
    	rep(i, 1, lim) rep(j, 1, n) {
    		f[i][j] = (LL)f[i-1][j-1] * i % MOD * j % MOD + f[i-1][j];
    		if(f[i][j] >= MOD) f[i][j] -= MOD;
    	}
    	if(Arrange == lim) return printf("%d
    ", f[lim][n]), 0;
    	
    	rep(i, n + 1, lim) X[i-n] = i, Y[i-n] = f[i][n];
    	inv[1] = 1;
    	rep(i, 2, lim) inv[i] = (LL)(MOD - MOD / i) * inv[MOD%i] % MOD;
    	printf("%d
    ", GetPoly(n << 1 | 1, Arrange));
    	
    	return 0;
    }
    
  • 相关阅读:
    html +JS 自学
    Linux下SVN多版本库管理
    Jenkins更换国内源
    Kubernetes Service
    Kubernetes Pod
    ubuntu下vim配置日常工作版本
    PYTHON替代MATLAB在线性代数学习中的应用(使用Python辅助MIT 18.06 Linear Algebra学习)
    mongodb 片键需要思考的问题
    SpringBoot--Easycode插件自定义模板
    Docker-概述
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/8510924.html
Copyright © 2011-2022 走看看