• calc BZOJ 2655


    calc

    【问题描述】

    一个序列a1,...,an是合法的,当且仅当:

    长度为给定的n。

    a1,...,an都是[1,A]中的整数。

    a1,...,an互不相等。

    一个序列的值定义为它里面所有数的乘积,即a1a2...an。

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

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

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

    【输入格式】

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

    【输出格式】

    一行结果。

    【样例输入】

    9 7 10007

    【样例输出】

    3611

    HINT

    【数据规模】

    0:A<=10,n<=10。

    1..3:A<=1000,n<=20。

    4..9:A<=10^9,n<=20。

    10..19:A<=10^9,n<=500。。

    全部:mod<=10^9,并且mod为素数,mod>A>n+1。


    题解:

    设 f[i][j] 为用不大于A的数组成的有序合法序列方案数

    转移方程:(是否选取 i 这个数字)

    题目要求无序,那么最后乘上 n! 即可

    细心观察一小下,发现它是一个有 2n 项的多项式 

    用拉格朗日插值法:

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long lo;
     9 inline int Get()
    10 {
    11     int x;
    12     char c;
    13     bool o = false;
    14     while((c = getchar()) < '0' || c > '9')
    15         if(c == '-') o = true;
    16     x = c - '0';
    17     while((c = getchar()) >= '0' && c <= '9')
    18         x = x * 10 + c - '0';
    19     return (o) ? -x : x;
    20 }
    21 const int maxn = 2333;
    22 int f[maxn][maxn];
    23 int fac[maxn];
    24 int x[maxn], y[maxn];
    25 int a, n, m, mo;
    26 int z, v, ans;
    27 int num;
    28 inline void Dp()
    29 {
    30     f[0][0] = 1;
    31     for(int i = 1; i <= m; ++i)
    32         for(int j = 0; j <= n; ++j)
    33         {
    34             f[i][j] = f[i - 1][j];
    35             if(j) f[i][j] += (lo) f[i - 1][j - 1] * i % mo;
    36             if(f[i][j] >= mo) f[i][j] -= mo;
    37         }
    38 }
    39 inline void Fac()
    40 {
    41     fac[0] = 1;
    42     for(int i = 1; i <= n; ++i) fac[i] = (lo) fac[i - 1] * i % mo;
    43 }
    44 inline void Sun()
    45 {
    46     num = 0;
    47     for(int i = 0; i <= m; ++i)
    48         if(f[i][n])
    49         {
    50             x[++num] = i, y[num] = f[i][n];
    51             if(num == (n << 1 | 1)) return;
    52         }
    53 }
    54 inline int Mod(int x)
    55 {
    56     if(x < 0) x += mo;
    57     return x;
    58 }
    59 inline int Pow(int x, int n)
    60 {
    61     int sum = 1;
    62     while(n)
    63     {
    64         if(n & 1) sum = (lo) sum * x % mo;
    65         x = (lo) x * x % mo;
    66         n >>= 1;
    67     }
    68     return sum;
    69 }
    70 int main()
    71 {
    72     a = Get(), n = Get(), mo = Get();
    73     m = n << 2;
    74     Dp();
    75     Fac();
    76     if(m >= a)
    77     {
    78         printf("%d", (lo) f[a][n] * fac[n] % mo);
    79         return 0;
    80     }
    81     Sun();
    82     z = 1;
    83     for(int i = 1; i <= num; ++i) z = (lo) z * Mod(a - x[i]) % mo;
    84     for(int i = 1; i <= num; ++i)
    85     {
    86         v = Mod(a - x[i]);
    87         for(int j = 1; j <= num; ++j)
    88             if(i != j)
    89                 v = (lo) v * Mod(x[i] - x[j]) % mo;
    90         ans = ans + (lo) y[i] * z % mo * Pow(v, mo - 2) % mo;
    91         if(ans >= mo) ans -= mo;
    92     }
    93     printf("%d", (lo) ans * fac[n] % mo);
    94 }
  • 相关阅读:
    .Net利用core实现简单的加解密例程全解析
    HTTPS抓包,利用telnet检查网络连接的几种方式
    每个人都应该知道的(cJSON)JSON处理库
    HashMap和Hashtable的区别
    Map集合
    Set集合
    同步异步以及泛型
    ArrayList的输出方式以及因子增长数
    (转)C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
    数据结构复习---最短路径
  • 原文地址:https://www.cnblogs.com/lytccc/p/6616576.html
Copyright © 2020-2023  润新知