zoukankan      html  css  js  c++  java
  • uoj22 外星人

    题意:给你一个数列ai,设d经过a的一个排列顺次对ai取模最后得到y。

    求使得|d-y|最小的y,以及可以达到y的排列数%998244353。

    ai,x<=5000,n<=1000.

    标程:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 const int mod=998244353;
     6 const int N=1005;
     7 int n,d,f[N][N*5],a[N];
     8 bool cmp(int A,int B){return A>B;}
     9 int main()
    10 {
    11     scanf("%d%d",&n,&d);
    12     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    13     sort(a+1,a+n+1,cmp);
    14     f[0][d]=1;
    15     for (int i=1;i<=n;i++)
    16     {
    17         for (int j=0;j<=d;j++) f[i][j]=((ll)f[i][j]+(ll)f[i-1][j]*(n-i)%mod)%mod;//注意j有可能等于d。 
    18        for (int j=0;j<=d;j++) f[i][j%a[i]]=((ll)f[i][j%a[i]]+f[i-1][j])%mod; 
    19     }
    20     for (int i=a[n]-1;i>=0;i--) if (f[n][i]) return printf("%d
    %d
    ",i,f[n][i]),0;
    21 }

    题解:dp

    分析后可以发现,如果排列中一个ai前面有aj比它小,那么这个ai就是无用的。

    反之,如果前面所有的aj都比ai大,那么ai就是关键点。

    先把所有元素从大到小排序。

    我们将元素从小到大加入,设当前加入的数是ai。那么之后的n-i个都已经加入,并且都比ai要小。那么ai是关键点当且仅当ai插入在全部n-i个小于ai的点之前。反之ai有n-i个间隔可插入且不是关键点。

    设f[i][j]为%前i个数(从大到小排序的前i个)后余数为j的方案数。

    1.ai作为关键点:f[i][j%a[i]]+=f[i-1][j];经过前i-1个数后对ai取模。

    2.ai为非关键点:f[i][j]+=(n-i)*f[i-1][j]。有n-i个间隔可供插入,这个点无效就不必考虑。

    时间复杂度O(nd)。

  • 相关阅读:
    Elasticsearch学习之SearchRequestBuilder的query类型
    Elasticsearch学习之SearchRequestBuilder常用方法说明
    Elasticsearch学习之head插件安装
    SpringBoot学习之Helloworld
    Http Header里的Content-Type
    柯里化
    VoltDB
    Docker
    PHP框架
    转载: 让我们聊聊Erlang的nif中资源的安全释放
  • 原文地址:https://www.cnblogs.com/Scx117/p/8693851.html
Copyright © 2011-2022 走看看