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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2655

    先设 f[i][j] 表示长度为 i 的序列,范围是 1~j 的答案;

    则 f[i][j] = f[i-1][j-1] * i * j + f[i][j-1],分别是选不选 j,选 j 的话放在哪个位置;

    看不出次数...据说这是个最高次数为 2i 的多项式,感性理解...

    知道了次数,就可以用拉格朗日插值算了,DP得到比较小的 2*n+1 个值,即可算出 x=A 的答案。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=505;
    int n,A,mod,f[xn][xn<<1],yy[xn<<1];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
    int pw(ll a,int b)
    {
      ll ret=1;
      for(;b;b>>=1,a=(a*a)%mod)
        if(b&1)ret=(ret*a)%mod;
      return ret;
    }
    int main()
    {
      A=rd(); n=rd(); mod=rd(); int m=2*n+1;
      //  f[0][0]=1;
      for(int j=0;j<=m;j++)f[0][j]=1;//!!!
      for(int i=1;i<=n;i++)
        for(int j=i;j<=m;j++)
          f[i][j]=((ll)f[i-1][j-1]*i%mod*j+f[i][j-1])%mod;
      if(A<=m){printf("%d
    ",f[n][A]); return 0;}
      for(int i=1;i<=m;i++)yy[i]=f[n][i];
      ll ans=0;
      for(int i=1;i<=m;i++)
        {
          ll s1=1,s2=1;
          for(int j=1;j<=m;j++)
        {
          if(i==j)continue;
          s1=(s1*(A-j)%mod+mod)%mod;// 
          s2=(s2*(i-j)%mod+mod)%mod;//
        }
          ans=(ans+s1*pw(s2,mod-2)%mod*yy[i]%mod)%mod;
        }
      printf("%lld
    ",ans);
      return 0;
    }
  • 相关阅读:
    Python中文乱码(转)
    一千行MySQL学习笔记
    pycharm在同目录下import,pycharm会提示错误,但是可以运行
    PyCharm3.0默认快捷键
    Sublime Text 3 快捷键
    window下spyder的快捷键
    Anaconda更新和第三方包更新
    PyCharm 教程
    centos7.9 源码编译安装php
    centos7.9 源码编译安装nginx
  • 原文地址:https://www.cnblogs.com/Zinn/p/10008133.html
Copyright © 2011-2022 走看看