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

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

    先考虑DP。dp[ i ][ j ]表示值域为 i 、选 j 个值的答案,则 dp[ i ][ j ] = dp[ i-1 ][ j ] + dp[ i-1 ][ j-1] * i * j 。两项分别表示一定不选/一定选第 i 个值。

    因为答案是值域大、个数小,所以考虑只看 dp[ ][ n ] ,即把值域看成自变量。

    不知怎么知道这个式子的次数是 2*n 。尝试用做几遍差分看什么时候数列都为0的方法来看,但得出应该是 2*n - 2 次才对呀……

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=4,K=12,M=505;
    ll dp[M][M],c[M];
    int pw(int x,int k)
    {
      int ret=1;while(k){if(k&1)ret*=x;x*=x;k>>=1;}return ret;
    }
    int main()
    {
      dp[0][0]=1;
      for(int i=1;i<=K;i++)
        for(int j=1;j<=N;j++)
          dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*i*j;
      for(int i=N;i<=K;i++)c[i]=dp[i][N];
      int cnt=0,nw=N;
      while(c[K])
        {
          for(int i=K;i>=nw;i--)
        c[i]-=c[i-1]; c[nw-1]=0;
          for(int i=1;i<=K;i++)
        printf("%6lld ",c[i]); puts("");
          nw++; cnt++;
        }
      printf("cnt=%d
    ",cnt);
      return 0;
    }
    打表观察

    以为值域<个数的dp无意义,于是选择 n~3*n 这 2*n+1 个值。但其实值域<个数的也能用。

    注意 x[ i ] - x[ j ] 有负数,最后(答案+mod)%mod。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=505;
    int n,A,mod,dp[N*3][N],ans;
    int pw(int x,int k)
    {
      int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;
    }
    int main()
    {
      scanf("%d%d%d",&A,&n,&mod);
      int lm=n*3;
      for(int i=0;i<=lm;i++)dp[i][0]=1;///
      for(int i=1;i<=lm;i++)
        for(int j=1;j<=i&&j<=n;j++)
          dp[i][j]=(dp[i-1][j]+(ll)dp[i-1][j-1]*i%mod*j)%mod;
      if(A<=lm)
        {
          printf("%d
    ",dp[A][n]);return 0;
        }
      int s0,s1;
      for(int i=n;i<=lm;i++)
        {
          s0=1; s1=1;//////
          for(int j=n;j<=lm;j++)
        {
          if(j==i)continue;
          s0=(ll)s0*(A-j)%mod;  s1=(ll)s1*(i-j)%mod;
        }
          ans=(ans+(ll)s0*pw(s1,mod-2)%mod*dp[i][n]%mod)%mod;
        }
      printf("%d
    ",(ans+mod)%mod);
      return 0;
    }
  • 相关阅读:
    ROS+clion多节点调试
    argparse模块用法实例详解
    Python3中的bytes和str类型
    elk日志过滤文档
    centos7普通用户无法切换为root用户处理
    Hyper-V迁移方案
    中小互联网电商(电商)公司研发部门组织架构
    基于Redis实现令牌桶限流
    异步与协程
    C# 同步上下文及死锁
  • 原文地址:https://www.cnblogs.com/Narh/p/10009669.html
Copyright © 2011-2022 走看看