zoukankan      html  css  js  c++  java
  • [TJOI2019]唱、跳、rap和篮球

    嘟嘟嘟


    TJ律师函警告


    20分暴力比较好拿,因为每一种学生可以理解为无限多,那么总方案数就是(C_{n} ^ {4}),然后我们枚举至少讨论cxk的有几组,容斥即可。
    需要注意的是,容斥的时候还要考虑每一组的位置可以不一样,因此要用插板法计算方案:(C_{i + n - 4i} ^ {i})


    剩下虽然没给暴力分,但其实能水到68。
    我们(O(n ^ 3))枚举(a, b, c)人数(这样就能算出来(d)的人数),设分别为(i, j, k, h)。然后根据可重集的全排列公式,方案数就是(frac{n!}{i! * j! * k! * h!})。这时候再枚举组数容斥减去即可。加几个break就能搞到68分。
    然后机房乱搞之神ssy在这个思路的基础上直接水到100分:把容斥放在最外层;发现有一部分可以与处理;记忆化。但这里我们就不细讲了。


    正解是NTT啥的,但我虽然会,可是懒得写。这里讲一个更简单的方法。
    考虑到上面的复杂度瓶颈在于(O(n ^ 3))枚举人数。我们可以换一种思路:枚举(a, b)之和(t),这样总方案数就是(sum _ {t = 0} ^ {n} (sum _ {i = 0} ^ {t} C_{t} ^ {i} * sum _ {k = 0} ^ {n - t} C_{n - t} ^ {k}) C_{n} ^ {t})
    然后发现中间的两个(sum)是底数(但愿能这么叫)相同的连续组合数之和,于是可以预处理。如果不考虑容斥,(O(n))就能求出来。
    然后我们在最外层套上容斥,和20分做法一样,枚举讨论cxk的有几组就行了。


    代码参见了题解,虽然不是很提倡循环的时候改变全局变量的方法,但有时候这么写是真的简便。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<assert.h>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e3 + 5;
    const ll mod = 998244353;
    In int read()
    {
      int ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    In void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
      freopen(".in", "r", stdin);
      freopen(".out", "w", stdout);
    #endif
    }
    
    int n, a, b, c, d;
    
    In ll inc(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;}
    
    ll C[maxn][maxn], sum[maxn][maxn];
    In void init()
    {
      C[0][0] = 1;
      for(int i = 1; i < maxn; ++i)
        {
          C[i][0] = 1;
          for(int j = 1; j <= i; ++j) C[i][j] = inc(C[i - 1][j - 1], C[i - 1][j]);
        }
      sum[0][0] = 1;
      for(int i = 0; i < maxn; ++i)
        {
          sum[i][0] = 1;
          for(int j = 1; j < maxn; ++j) sum[i][j] = inc(sum[i][j - 1], C[i][j]);
        }
    }
    
    In ll calc(int t, int L, int R)
    {
      if(L > R) return 0;
      if(L <= 0) return sum[t][R];
      return inc(sum[t][R], mod - sum[t][L - 1]);
    }
    
    int main()
    {
      //MYFILE();
      n = read();
      a = min(n, read()), b = min(n, read()), c = min(n, read()), d = min(n, read());
      init();
      ll ans = 0;
      for(int t = 0; n >= 0 && a >= 0 && b >= 0 && c >= 0 && d >= 0; ++t)
        {
          ll tp = 0;
          for(int i = 0; i <= n; ++i)
    	tp = inc(tp, C[n][i] * calc(i, i - b, i) % mod * calc(n - i, n - i - d, c) % mod);
          tp = tp * C[n + t][t] % mod;
          ans = inc(ans, (t & 1) ? mod - tp : tp);
          n -= 4, --a, --b, --c, --d; 
        }
      write(ans), enter;
      return 0;
    }
    
  • 相关阅读:
    微博三方登录流程
    完善注册接口
    vue检查用户名是否重复
    转载:TypeError: Cannot read property 'compilation' of undefined vue 打包运行npm run build 报错
    转载:mybatis中<![CDATA[]]>的作用
    转载:eclipse中web项目小地球没了
    转载:解决npm安装时出现run `npm audit fix` to fix them, or `npm audit` for details
    转载:IDEA lombok插件的安装和使用
    转载:idea配置svn及使用
    RESTful风格编程
  • 原文地址:https://www.cnblogs.com/mrclr/p/10959901.html
Copyright © 2011-2022 走看看