• UOJ450 复读机


    题意:n个位置,k种颜色。求有多少种方案使得每种颜色恰出现d的倍数次。

    解:d=1就快速幂,n,k很小就DP,记得乘组合数来分配位置。

    d = 2 / 3的时候,考虑生成函数。

    f(x) = ∑[d | i] / (i!)

    然后发现d = 2的时候就是(ex + e-x) / 2,这个东西的k次方可以用二项式定理展开,然后O(klogn)算,log是快速幂。

    d = 3的时候用单位根反演,O(k2)枚举系数,同样算。因为我不想学单位根反演就没写...

     1 #include <bits/stdc++.h>
     2 
     3 typedef long long LL;
     4 
     5 const int N = 500010, MO = 19491001;
     6 
     7 int n, k, d;
     8 
     9 inline int qpow(int a, int b) {
    10     int ans(1);
    11     while(b) {
    12         if(b & 1) {
    13             ans = (LL)ans * a % MO;
    14         }
    15         a = (LL)a * a % MO;
    16         b = b >> 1;
    17     }
    18     return ans;
    19 }
    20 
    21 namespace DP {
    22     int f[110][1010], C[1010][1010];
    23     inline void solve() {
    24         f[0][0] = 1;
    25         for(int i = 0; i <= 1000; i++) {
    26             C[i][0] = C[i][i] = 1;
    27             for(int j = 1; j < i; j++) {
    28                 C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MO;
    29             }
    30         }
    31         for(int i = 0; i < k; i++) {
    32             for(int j = 0; j <= n; j++) {
    33                 for(int p = 0; j + p <= n; p += d) {
    34                     (f[i + 1][j + p] += (LL)f[i][j] * C[n - j][p] % MO) %= MO;
    35                 }
    36             }
    37         }
    38         printf("%d
    ", f[k][n]);
    39         return;
    40     }
    41 }
    42 
    43 namespace D2 {
    44 
    45     int fac[N], inv[N], invn[N];
    46 
    47     inline int C(int n, int m) {
    48         if(n < 0 || m < 0 || n < m) return 0;
    49         return (LL)fac[n] * invn[m] % MO * invn[n - m] % MO;
    50     }
    51 
    52     inline void solve() {
    53         fac[0] = inv[0] = invn[0] = 1;
    54         fac[1] = inv[1] = invn[1] = 1;
    55         for(int i = 2; i <= k; i++) {
    56             fac[i] = (LL)fac[i - 1] * i % MO;
    57             inv[i] = (LL)inv[MO % i] * (MO - MO / i) % MO;
    58             invn[i] = (LL)invn[i - 1] * inv[i] % MO;
    59         }
    60         
    61         int ans = 0;
    62         for(int i = 0; i <= k; i++) {
    63             ans += (LL)C(k, i) * qpow(2 * i - k, n) % MO;
    64             ans %= MO;
    65         }
    66         int temp = qpow((MO + 1) / 2, k);
    67         
    68         printf("%lld
    ", ((LL)temp * ans % MO + MO) % MO);
    69         return;
    70     }
    71 }
    72 
    73 int main() {
    74 
    75     scanf("%d%d%d", &n, &k, &d);
    76     if(d == 1) {
    77         printf("%d
    ", qpow(k, n));
    78         return 0;
    79     }
    80     if(n <= 1000 && k <= 100) {
    81         DP::solve();
    82         return 0;
    83     }
    84     if(d == 2) {
    85         D2::solve();
    86         return 0;
    87     }
    88     return 0;
    89 }
    60分代码
  • 相关阅读:
    linux下使用g++编译cpp工程
    c++字符串互相转换
    MFC双缓冲绘图实例
    Python进阶之迭代器和生成器
    <大话设计模式>笔记
    配置程序成为Linux服务
    Django的设计模式
    Django ModelForm修改默认的控件属性
    Android活动生命周期
    MySQL必知必会笔记
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/11111449.html
Copyright © 2020-2023  润新知