CF 997C Sky Full of Stars

2023-05-16

          • 传送门
          • 题目大意
          • 思路
          • 参考代码
          • 总结

传送门
题目大意

有一个 n×n(n106) n × n ( n ≤ 10 6 ) 的正方形网格。用三种颜色对每个格子染色,求有多少种染色方案使得至少一行或一列是同一种颜色。答案对 998244353 998244353 取模。

思路

正难则反,考虑求不存在一行或一列同色的方案数。结果反着也难……

正着做,考虑容斥。这里有行和列两个参数,如何容斥呢?我们定义 Ai A i 表示第 i i 行的颜色都相同的染色方案,用 Bi 表示第 j j 行的颜色都相同的染色方案,那么我们要求的是:

|A1A2AnB1B2Bn|

把上面这个式子具体地写出来,你就知道该如何容斥了:设至少有 i i 行的颜色一样,至少有 j 列的颜色一样,我们枚举 i+j i + j 来容斥。这种具体写出并集式子的方法可以了解一下。

那么现在的问题是如何计算选了至少 i i 行和 j 列时的方案数。当 i=j=0 i = j = 0 时,显然为 3n2 3 n 2 ;当 i i j 其中之一为 0 0 时,先枚举是哪些行(或者列,下同),再枚举这些行是什么颜色,再枚举剩下的颜色,那么显然是 Cni3i3n(ni);当 i,j>0 i , j > 0 时,注意到那些同色的行和列颜色都相同,因此答案为 CinCjn33(ni)(nj) C n i C n j ⋅ 3 ⋅ 3 ( n − i ) ( n − j )

不妨设:

f(i,j)=3i3n(ni)3j3n(nj)3(ni)(nj)+1i=0j=0i,j>0 f ( i , j ) = { 3 i ⋅ 3 n ( n − i ) i = 0 3 j ⋅ 3 n ( n − j ) j = 0 3 ( n − i ) ( n − j ) + 1 i , j > 0

那么最终答案是:
i=0nj=min(1,i)nCinCjnf(i,j)(1)i+j+1 ∑ i = 0 n ∑ j = min ( 1 , i ) n C n i C n j f ( i , j ) ( − 1 ) i + j + 1

注意上式 (1) ( − 1 ) 的指数。于是我们立刻得到一个 O(n2) O ( n 2 ) 的做法。


我们不妨把 i=0 i = 0 或者 j=0 j = 0 的情况单独拿出来计算。由于总共只有 O(n) O ( n ) 项,因此这一步的时间复杂度为 O(n) O ( n ) 。剩下的是:

i=1nj=1nCinCjn3(ni)(nj)+1(1)i+j+1 ∑ i = 1 n ∑ j = 1 n C n i C n j 3 ( n − i ) ( n − j ) + 1 ( − 1 ) i + j + 1


很自然想到按照 i i j 分开,把只与 i i 有关的乘数移到外面去。在此之前,需要先把 (ni)(nj) 拆开。

i=1nj=1nCinCjn3n2+13in3jn3ij(1)i(1)j(1) ∑ i = 1 n ∑ j = 1 n C n i C n j 3 n 2 + 1 ⋅ 3 − i n ⋅ 3 − j n ⋅ 3 i j ⋅ ( − 1 ) i ⋅ ( − 1 ) j ⋅ ( − 1 )

把能提出去的都提出去:
(1)3n2+1i=1nCin3in(1)ij=1nCjn3jn(1)j3ij ( − 1 ) ⋅ 3 n 2 + 1 ∑ i = 1 n C n i ⋅ 3 − i n ⋅ ( − 1 ) i ∑ j = 1 n C n j ⋅ 3 − j n ⋅ ( − 1 ) j ⋅ 3 i j

要是没有那个 3ij 3 i j ,这道题就做完啦!这个 3ij 3 i j 怎么解决呢?

观察右边的和式,整理一下得:

j=1nCjn(3n+i)j ∑ j = 1 n C n j ⋅ ( − 3 − n + i ) j

这这么像二项式定理,就直接套用二项式定理咯。只不过 j0 j ≠ 0 ,所以要减去 j=0 j = 0 的情况:
(13n+i)n1 ( 1 − 3 − n + i ) n − 1

现在的答案是:
(1)3n2+1i=1nCin3in(1)i((13n+i)n1) ( − 1 ) ⋅ 3 n 2 + 1 ∑ i = 1 n C n i ⋅ 3 − i n ⋅ ( − 1 ) i ⋅ ( ( 1 − 3 − n + i ) n − 1 )

使用快速幂,时间复杂度 O(nlogn) O ( n log ⁡ n )

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef int INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
}

const int mod = 998244353;
LL power(LL x, int y)
{
    LL ret = 1;
    while (y)
    {
        if (y & 1) ret = ret * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return ret;
}
const int inv3 = power(3, mod - 2);

const int maxn = int(1e6) + 5;
int n;
int fac[maxn];
int invFac[maxn];
int power1[maxn];
int power2[maxn];
int invPower1[maxn];
int invPower2[maxn];
void init()
{
    fac[0] = 1;
    for (int i = 1; i <= n; i++)
        fac[i] = (LL)fac[i - 1] * i % mod;
    invFac[n] = power(fac[n], mod - 2) % mod;
    for (int i = n - 1; ~i; i--)
        invFac[i] = (LL)invFac[i + 1] * (i + 1) % mod;
    power1[0] = 1;
    for (int i = 1; i <= n; i++)
        power1[i] = (LL)power1[i - 1] * 3 % mod;
    power2[0] = 1;
    for (int i = 1; i <= n; i++)
        power2[i] = (LL)power2[i - 1] * power1[n] % mod;
    invPower1[0] = 1;
    for (int i = 1; i <= n; i++)
        invPower1[i] = (LL)invPower1[i - 1] * inv3 % mod;
    invPower2[0] = 1;
    for (int i = 1; i <= n; i++)
        invPower2[i] = (LL)invPower2[i - 1] * invPower1[n] % mod;
}
inline LL C(int down, int up)
{
    return down < up ? 0 : (LL)fac[down] * invFac[up] % mod * invFac[down - up] % mod;
}

void run()
{
    n = readIn();
    init();

    LL ans = 0;
    for (int i = 1, sig = 1; i <= n; i++, sig = -sig)
        ans = (ans + (LL)C(n, i) * power1[i] % mod * power2[n - i] * sig) % mod;
    ans = (ans * 2) % mod;

    LL base = (LL)-power2[n] * 3 % mod;
    base = (base + mod) % mod;

    LL sum = 0;
    for (int i = 1, sig = -1; i <= n; i++, sig = -sig)
    {
        sum = (sum + (LL)C(n, i) * invPower2[i] * sig % mod *
            (power(1 - invPower1[n - i], n) - 1)) % mod;
    }
    ans = (ans + base * sum) % mod;
    ans = (ans + mod) % mod;
    printOut(ans);
}

int main()
{
    run();
    return 0;
}
总结

这道题本身不难,但还是看题解才做出来的,有几个原因:

  1. 出发点反了,没有想容斥,而是正难则反去了;
  2. 后面没有想到二项式定理。

也就是说这道题就是个容斥原理和二项式定理。二项式定理没什么好说的,注意它的结构。容斥原理可以把要算的内容具体的写出来,如果能写成并集形式就可以容斥了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CF 997C Sky Full of Stars 的相关文章

  • Luogu 2178 [NOI 2015] 品酒大会

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 做了两个星期的题 xff0c 自己做出来的才只有这一道 xff0c 唉 xff0c 我太弱啦 xff01 我们考虑第一问怎么做 题目中相似的概念
  • Luogu 1117 [NOI 2016] 优秀的拆分

    传送门思路利用后缀数组解决重复子串问题注意事项参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连暴力都想不到 xff0c 唉 xff0c 我太弱啦 xff01 考虑暴力法 xff0c 可以枚举一个中间点
  • Luogu 1712 [NOI 2016] 区间

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 这么个傻逼题 xff0c 居然把离散化写错了 xff0c 唉 xff0c 我太弱啦 xff01 显然我们可以考虑枚举最短长度和最长长度 xff0
  • CF 977F Consecutive Subsequence

    传送门思路参考代码 传送门 思路 CF 的第一场 div3 xff0c 在我提交了一份有错的代码后突然不能提交了 xff0c 在跑什么 System Testing xff0c 我就跟它杠上了 xff0c 直到它评测完 唉 xff0c 我太
  • CF 7D Palindrome Degree

    传送门思路参考代码 传送门 思路 不是马拉车加随便 DP 乱搞 xff1f 本来想复习一下马拉车的 xff0c 结果拉出了许多事端 xff08 修复了 OI Learner Judge 的严重 bug 一个害我调了两节课的 bug xff0
  • Luogu 3822 [NOI 2017] 整数

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 当年网同这道题还拿了 16 16 分 xff0c 现在一分都不会做了 xff0c 唉 xff0c 我太弱啦 xff01 这道题其实是很不错的 x

随机推荐

  • 【Go】go语言中切片的长度变化后容量的变化

    一 新增信息长度 43 当前长度 lt 61 当前容量 span class token keyword func span span class token function printSlice span span class toke
  • APIO 2018 Practice Session T1 Wedding cake

    没有传送门题目大意思路参考代码熟悉环境 没有传送门 题目大意 给你一个长度为 n n 的正整数序列 a i ai xff0c 要求构造出 n n 个小数 使得它们的和为 1 1 xff0c 且每个数小数点后恰好有
  • APIO 2018 Practice Session T3 / CF 936C Lock Puzzle

    传送门题目大意思路参考代码总结 传送门 题目大意 给你一个字符串 origin xff0c 一个字符串 target xff0c 长度均为 n n 要求在 3 n 3n xff08 5 2 n 5 2
  • APIO 2018 游记

    Day 0Day 1Day 2Day 3Day 4 Day 0 早上 4 4 点就上车去机场赶那 7 7 点的飞机 感觉很困 xff0c 所以在飞机上就这么睡过去了 北京是个好地方 xff0c 但是与我无关 下飞机后 xff0c 我们一行人
  • Luogu 2375 [NOI 2014] 动物园

    文章目录 传送门思路参考代码Review 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连 KMP 也不会 xff0c WA 飞了 xff0c 唉 xff0c 我太弱啦 xff01 首先 xff0c 原始的 K
  • Luogu 2114 [NOI 2014] 起床困难综合症

    传送门思路参考代码 传送门 思路 按位贪心 但是我太弱了 xff0c 明明可以 O n O n 预处理 xff0c 我却只会 O 32 n O
  • Luogu 2354 [NOI 2014] 随机数生成器

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 这么一个傻逼题 xff0c 我却看成了要你构造一种交换方案使得答案最小 xff0c 结果后面的额外交换是题目给定的 唉 xff0c 我太弱啦 x
  • Luogu 2305 [NOI 2014] 购票

    传送门思路别人家的题解弱化的传送门 xff08 Luogu 3994 高速公路 xff09 参考代码 对于没有距离限制的 50 分 参考代码 对于 100 分的数据参考代码Remarks 传送门 思路 唉 xff0c 我太弱了 xff0c
  • Luogu 1224 [NOI 2013] 向量内积

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 听都没有听说过这类题 xff0c 唉 xff0c 我太弱啦 xff01 显然这道题可以在 O n 2 d O n 2
  • Luogu 1397 [NOI 2013] 矩阵游戏

    传送门思路正解参考代码Remarks 传送门 思路 唉 xff0c 我太弱了 xff0c T1 都做不来 xff0c 唉 xff0c 我太弱啦 xff01 显然这个题可以用矩阵快速幂在 O log n O log n
  • Luogu 2414 [NOI 2011] 阿狸的打字机

    文章目录 传送门思路参考代码总结 传送门 思路 首先我们甚至不能单独保存每个字符串 xff0c 因为总长度可以达到 O n 2
  • kali新手入门教学(10)--ping的讲解

    Ping 是 Windows 和 Linux 都自带的一个扫描工具 xff0c 用于校验与远程计算机或本机的连接 只有在安装 TCP IP 协议之后才能使用该命令 Ping 命令通过向计算机发送 ICMP 回应 报文并且监听回应报文的返回
  • Luogu 3628 [APIO 2010] 特别行动队

    传送门思路参考代码 传送门 BZOJ 思路 设 f i f i 表示将 1 i 1 i 的士兵编
  • Luogu 1399 [NOI 2013] 快餐店

    传送门思路参考代码Remarks总结 传送门 思路 发现这是一棵环套树 那首先我们会想到树上的情况 如果这是一棵树 xff0c 我们自然会联想到树的直径 xff0c 自然会想到对于树而言 xff0c 答案为直径长度的一半 证明 用反证法 假
  • GDB for C++ in Linux

    这篇文章主要讲讲如何在 Linux 下使用 GDB xff0c 当然 xff0c 就指令而言在 Windows 下也适用 环境Items 编译启动退出加载文件查看源代码断点 插入断点删除断点 运行程序查看变量控制程序执行 继续下一步单步进入
  • CF 1000F One Occurrence

    传送门题目大意思路参考代码总结 时光如梭 xff0c Codeforces 的题号还是三位数的时代已经过去 xff1b 量子语言原来已经来临 传送门 题目大意 给定一个长度为 n n 的序列 a a xff0c 有 m m 个
  • CF 993E Nikita and Order Statistics

    传送门题目大意思路参考代码 传送门 题目大意 给你一个数组 a 1 n a 1 n xff0c 对于 k 61 0 n
  • CF 997A Convert to Ones

    传送门题目大意思路参考代码总结 传送门 题目大意 给你一个长度为 n n 3 10 5 n n 3 10
  • CF 997B Roman Digits

    传送门题目大意思路参考代码总结 传送门 题目大意 现在规定罗马数字只有 4 4 个字符 I V X L 分别代表 1 1 5 5 10 10 50 50
  • CF 997C Sky Full of Stars

    传送门题目大意思路参考代码总结 传送门 题目大意 有一个 n n n 10 6 n n n 10