In school training [group]

Keywords: PHP iOS

meaning of the title

Divide n numbers into several groups. The minimum number in each group cannot be more than the total number of elements in this group. Find the number of schemes. N<=2000.

 

Reflection

If we get a partition of n numbers, we can simply find out the number of schemes. After sorting it from large to small, let larger I be the number of numbers greater than or equal to I, b[i] be the size of group I, sum be the prefix sum of B, then for group I, its contribution is C(larger[b[i]]-sum[i-1],b[i]). At the same time, if there is c bi, then divide by c!.

Because it is only related to the minimum number and the number of the minimum number, Let f[i][j][k] be the number of the first I selected, the current minimum bi is j, and there are k bi. Only when k is 1, prefixes and optimizations can be used. When k is not 1, it is transferred from k-1 and divided by K. Complexity O(n^3).

Note that J * k < = I, only n^2logn useful States, can be directly opened dynamically.

 

Code

  1 #include<bits/stdc++.h>
  2 #define mod 998244353
  3 using namespace std;
  4 typedef long long int ll;
  5 const int maxn=2E3+5;
  6 int n,a[maxn],larger[maxn],b[maxn],top;
  7 int ans,fac[maxn],invC[maxn],sum[maxn][maxn],inv[maxn];
  8 int*f[maxn][maxn];
  9 int C[maxn][maxn];
 10 ll qpow(ll x,ll y)
 11 {
 12     ll base=x,ans=1;
 13     while(y)
 14     {
 15         if(y&1)
 16             ans=ans*base%mod;
 17         base=base*base%mod;
 18         y>>=1;
 19     }
 20     return ans;
 21 }
 22 inline void add(int&x,int y)
 23 {
 24     ll g=(ll)x+(ll)y;
 25     if(g>=mod)
 26         g-=mod;
 27     x=g;
 28 }
 29 void init()
 30 {
 31     fac[0]=1;
 32     for(int i=1;i<=n;++i)
 33         fac[i]=(ll)fac[i-1]*(ll)i%mod;
 34     invC[n]=qpow(fac[n],mod-2);
 35     for(int i=n-1;i>=0;--i)
 36         invC[i]=(ll)invC[i+1]*(ll)(i+1)%mod;
 37     for(int i=1;i<=n;++i)
 38         inv[i]=qpow(i,mod-2);
 39     C[0][0]=1;
 40     for(int i=1;i<=n;++i)
 41     {
 42         C[i][0]=1;
 43         for(int j=1;j<=i;++j)
 44         {
 45             C[i][j]=C[i-1][j];
 46             add(C[i][j],C[i-1][j-1]);
 47         }
 48     }
 49 }
 50 inline int read()
 51 {
 52     char ch=getchar();
 53     while(ch<'0'||'9'<ch)
 54         ch=getchar();
 55     int sum=ch-'0';
 56     ch=getchar();
 57     while('0'<=ch&&ch<='9')
 58     {
 59         sum=sum*10+ch-'0';
 60         ch=getchar();
 61     }
 62     return sum;
 63 }
 64 int main()
 65 {
 66     freopen("game.in","r",stdin);
 67     freopen("game.out","w",stdout);
 68     ios::sync_with_stdio(false);
 69     n=read();
 70     init();
 71     for(int i=1;i<=n;++i)
 72     {
 73         a[i]=read();
 74         if(a[i]==0)
 75         {
 76             cout<<0<<endl;
 77             return 0;
 78         }
 79         ++larger[a[i]];
 80     }
 81     for(int i=n-1;i>=1;--i)
 82         larger[i]+=larger[i+1];
 83     for(int i=1;i<=n;++i)
 84         for(int j=1;j<=i+1;++j)
 85         {
 86             f[i][j]=new int[i/j+4];
 87             for(int k=0;k<=i/j+3;++k)
 88                 f[i][j][k]=0;
 89         }
 90     for(int j=1;j<=n+1;++j)
 91     {
 92         f[0][j]=new int[3];
 93         for(int k=0;k<=2;++k)
 94             f[0][j][k]=0;
 95     }
 96     f[0][n+1][0]=1;
 97     for(int i=1;i<=n+1;++i)
 98         sum[0][i]=1;
 99     for(int i=1;i<=n;++i)
100     {
101         for(int j=1;j<=i;++j)
102         {
103             if(sum[i-j][j+1])
104                 f[i][j][1]=(ll)sum[i-j][j+1]*(ll)C[larger[j]-i+j][j]%mod;
105             for(int k=2;i-j*k>=0;++k)
106             {
107                 if(f[i-j][j][k-1])
108                     f[i][j][k]=(ll)f[i-j][j][k-1]*(ll)inv[k]%mod*(ll)C[larger[j]-i+j][j]%mod;
109             }
110         }
111         for(int j=i+1;j>=1;--j)
112         {
113             sum[i][j]=sum[i][j+1];
114             for(int k=1;i-j*k>=0;++k)
115                 add(sum[i][j],f[i][j][k]);
116         }
117     }
118     ans=0;
119     for(int i=1;i<=n;++i)
120         for(int j=1;n-i*j>=0;++j)
121             add(ans,f[n][i][j]);
122     cout<<ans<<endl;
123     return 0;
124 }

Posted by mananx on Thu, 31 Oct 2019 16:08:28 -0700