zoukankan      html  css  js  c++  java
  • bzoj 2566 calc 拉格朗日插值

    calc

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 377  Solved: 226
    [Submit][Status][Discuss]

    Description


      一个序列a1,...,an是合法的,当且仅当:
      长度为给定的n。
      a1,...,an都是[1,A]中的整数。
      a1,...,an互不相等。
      一个序列的值定义为它里面所有数的乘积,即a1a2...an。
      求所有不同合法序列的值的和。
      两个序列不同当且仅当他们任意一位不一样。
      输出答案对一个数mod取余的结果。

    Input

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

    Output

      一行结果。

    Sample Input

    9 7 10007


    Sample Output

    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

    Source

    不得不说dp设的也是十分好的,估计自己还想不出。

    f[i][j]表示,前i个元素中,选择了j个的方案数,这个转移是怎么样的呢?

    f[i][j]=f[i-1][j-1]*i*j+f[i-1][j],这个转移中的第二个十分显然,第一个是什么意思,就是选择了i这个元素,

    插入到j中的任意一个位置,就是j个位置离随便哪个位置都可以,然后根据乘法的分配律,结合一下,就可以了。

    当然j可以大于i,就因为i可以插到后面的位置。

    就算想出了这一步,下面发现这个表是一个几次的多项式我基本上不可能会发现

    某大佬打了这个表,然后这个多项式怎么搞出来的真的有点厉害

    但是这个多项式是没用的,因为这个多项式的系数是变化的,所以没有什么用

    有没有一个多项式的系数是不变的呢?
    然后就有大佬发现了

    发现了这个,即f[i][j]的系数只和j有关,是一个最高项系数是2*j的多项式,然后就稳了,

    这样只需要求出2*n+1个点就可以插值了,朗格朗日插值求一下m这个位置的值即可。

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<iostream>
     5 #include<algorithm>
     6 
     7 #define N 1007
     8 #define ll long long
     9 using namespace std;
    10 inline int read()
    11 {
    12     int x=0,f=1;char ch=getchar();
    13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 
    18 int n,m;
    19 ll p,ans;
    20 ll f[N][N];
    21 
    22 ll fast_pow(ll a,ll b)
    23 {
    24     ll ans=1;
    25     while(b)
    26     {
    27         if (b&1) (ans*=a)%=p;
    28         (a*=a)%=p;
    29         b>>=1;
    30     }
    31     return ans;
    32 }
    33 void Lagrange()
    34 {
    35     for (int i=0;i<=2*n;i++)
    36     {
    37         ll s1=1,s2=1;
    38         for (int j=0;j<=2*n;j++)
    39             if (j!=i)
    40             {
    41                 (s1*=(m-j))%=p;
    42                 (s2*=(i-j))%=p;
    43             }
    44         (ans+=f[i][n]*s1%p*fast_pow(s2,p-2)%p)%=p;    
    45     }
    46 }
    47 int main()
    48 {
    49     m=read(),n=read(),p=read();
    50     f[0][0]=1;
    51     for (int i=1;i<=2*n;i++)
    52     {
    53         f[i][0]=f[i-1][0];
    54         for (int j=1;j<=n;j++)
    55             f[i][j]=(f[i-1][j-1]*i%p*j+f[i-1][j])%p;
    56     }
    57     if (m<=2*n)
    58     {
    59         printf("%lld
    ",f[m][n]);
    60         return 0;
    61     }
    62     
    63     Lagrange();
    64     ans=(ans%p+p)%p;
    65     
    66     printf("%lld
    ",ans);
    67 }
  • 相关阅读:
    wireshark如何抓取本机包
    模拟post请求方法
    Spring Boot中使用RabbitMQ
    Dubbo注册中心的四种配置方式详解
    spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情
    zookeeper 大量连接断开重连原因排查
    分布式一致性协议之:Gossip(八卦)算法
    MongoDB分析工具之一:explain()语句分析工具
    MongoDB分析工具之二:MongoDB分析器Profile
    MySQL安装
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8645926.html
Copyright © 2011-2022 走看看