• CodeCraft-19 and Codeforces Round #537 (Div. 2)


    Problem  CodeCraft-19 and Codeforces Round #537 (Div. 2) - D. Destroy the Colony

    Time Limit: 2000 mSec

    Problem Description

    Input

     

    Output

     For each question output the number of arrangements possible modulo 10^9+7.

    Sample Input

    abba
    2
    1 4
    1 2

    Sample Output

    2
    0

    题解:这个题的每一部分都比较简单,加在一起就有难度了。关于组合数学的部分就不说了,比较简单,这个题的精华在于dp的部分,对于每次的询问,相当于强制让两种字符不在左边(或者不在右边),也就是在原始的dp递推方程中要跳过这两个字符的方案数,如果每次都重新递推,递推的复杂度是O(n * k),一共有k^2个组合,复杂度会炸,这时就要考虑利用之前dp的信息来减少递推的计算量,新的tmp_dp[j]的状态定义长度为j的,没有第i种字符的方案数,这其实就是长度为j的总方案数减去强制有第i种字符的方案数,而强制有i的方案数就应该是没有i的长度为j - cnt[i]的方案数,这恰好就是tmp_dp[j - cnt[i]],因此tmp[j] = dp[j] - tmp_dp[j - cnt[i]],可以在O(n)的时间内完成递推,一共有k^2个组合,因此复杂度时O(n * k^2),可以接受。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define REP(i, n) for (int i = 1; i <= (n); i++)
      6 #define sqr(x) ((x) * (x))
      7 
      8 const int maxn = 100000 + 10;
      9 const int maxm = 200000 + 100;
     10 const int maxs = 52;
     11 
     12 typedef long long LL;
     13 typedef pair<int, int> pii;
     14 typedef pair<double, double> pdd;
     15 
     16 const LL unit = 1LL;
     17 const int INF = 0x3f3f3f3f;
     18 const LL Inf = 0x3f3f3f3f3f3f3f3f;
     19 const double eps = 1e-14;
     20 const double inf = 1e15;
     21 const double pi = acos(-1.0);
     22 const LL mod = 1000000007;
     23 
     24 inline int cal(char ch)
     25 {
     26     if (isupper(ch))
     27         return ch - 'A' + 26;
     28     return ch - 'a';
     29 }
     30 
     31 LL pow_mod(LL x, LL n, LL mod)
     32 {
     33     LL ans = 1, base = x;
     34     while (n)
     35     {
     36         if (n & 1)
     37             ans = (ans * base) % mod;
     38         base = (base * base) % mod;
     39         n >>= 1;
     40     }
     41     return ans;
     42 }
     43 
     44 void Add(LL &a, LL b)
     45 {
     46     a += b;
     47     if (a > mod)
     48         a -= mod;
     49 }
     50 
     51 void Sub(LL &a, LL b)
     52 {
     53     a -= b;
     54     if (a < 0)
     55         a += mod;
     56 }
     57 
     58 string str;
     59 LL n;
     60 LL cnt[maxs];
     61 LL fact[maxn], inv[maxn];
     62 LL dp[maxn], tmp_dp[maxn];
     63 LL ans[maxs][maxs];
     64 
     65 int main()
     66 {
     67     ios::sync_with_stdio(false);
     68     cin.tie(0);
     69     //freopen("input.txt", "r", stdin);
     70     //freopen("output.txt", "w", stdout);
     71     cin >> str;
     72     n = str.size();
     73     for (int i = 0; i < n; i++)
     74     {
     75         cnt[cal(str[i])]++;
     76     }
     77     fact[0] = fact[1] = 1;
     78     for (LL i = 2; i <= n; i++)
     79     {
     80         fact[i] = (fact[i - 1] * i) % mod;
     81     }
     82     inv[n] = pow_mod(fact[n], mod - 2, mod);
     83     for (LL i = n - 1; i >= 0; i--)
     84     {
     85         inv[i] = (inv[i + 1] * (i + 1)) % mod;
     86     }
     87     LL num = (fact[n / 2] * fact[n / 2]) % mod;
     88     for (int i = 0; i < maxs; i++)
     89     {
     90         num = (num * inv[cnt[i]]) % mod;
     91     }
     92     dp[0] = 1;
     93     for (int i = 0; i < maxs; i++)
     94     {
     95         if (!cnt[i])
     96             continue;
     97         for (int j = n; j >= cnt[i]; j--)
     98         {
     99             Add(dp[j], dp[j - cnt[i]]);
    100         }
    101     }
    102     for (int i = 0; i < maxs; i++)
    103     {
    104         ans[i][i] = dp[n / 2];
    105     }
    106     for (int i = 0; i < maxs; i++)
    107     {
    108         if (!cnt[i])
    109             continue;
    110         for (int i = 0; i <= n; i++)
    111             tmp_dp[i] = dp[i];
    112         for (int t = cnt[i]; t <= n; t++)
    113         {
    114             Sub(tmp_dp[t], tmp_dp[t - cnt[i]]);
    115         }
    116         for (int j = i + 1; j < maxs; j++)
    117         {
    118             if (!cnt[j])
    119                 continue;
    120             for (int t = cnt[j]; t <= n; t++)
    121             {
    122                 Sub(tmp_dp[t], tmp_dp[t - cnt[j]]);
    123                 ans[i][j] = (2LL * tmp_dp[n / 2]) % mod;
    124                 ans[j][i] = ans[i][j];
    125             }
    126             for (int t = n; t >= cnt[j]; t--)
    127                 Add(tmp_dp[t], tmp_dp[t - cnt[j]]);
    128         }
    129     }
    130     int q;
    131     cin >> q;
    132     int x, y;
    133     while (q--)
    134     {
    135         cin >> x >> y;
    136         int l = cal(str[x - 1]);
    137         int r = cal(str[y - 1]);
    138         cout << (num * ans[l][r]) % mod << "
    ";
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    python2 与python3 区别的总结 持续更新中......
    基础数据类型初识(三)字典
    基础数据类型初识(二)列表,元组
    基本数据类型初识(一)数字,字符串
    python基础知识(理论)
    进程池 和 管道 , 进程之间的 信息共享
    并发编程
    进程 和 多进程
    计算机系统的发展史
    网络编程 黏包
  • 原文地址:https://www.cnblogs.com/npugen/p/10801504.html
Copyright © 2020-2023  润新知