Codeforces997C Sky Full of Stars 【FMT】【组合数】

Stella981
• 阅读 808

题目大意:

一个$n*n$的格子,每个格子由你填色,有三种允许填色的方法,问有一行或者一列相同的方案数。

题目分析:

标题的FMT是我吓人用的。

一行或一列的问题不好解决,转成它的反面,没有一行和一列相同的方案数。

从一个方向入手,比如列,把一列看成一个整体。把颜色看成二进制数,$001$,$010$,$100$。

那么一列构成了一个长度为$3n$的二进制数,$n$列之间互相与出来的结果为$0$。实际我要统计这个东西。

注意到每一列的取法是不能取相同颜色的,所以剔除相同。之后我们得到了每一列可选的情况。

将它做FMT,之后做$n$次方,然后做IFMT,$0$位上的就是答案。用$9^n$减去这个数字就行。

直接做的时间复杂度是$O(n*2^n)$的,我们远不能承受。

但是我们有用的状态却不多,甚至还有规律。比如FMT后的某个位$bit$如果每三位出现两个$1$那么这个的FMT值一定是$0$,然后如果每三位只有$1$个$1$那么该位贡献$1$次,否则贡献$3$次。

然后是IFMT的还原问题,经过观察,不难发现如果某个位$bit$的$1$的个数为奇数,那么对$0$位产生减的影响,否则产生加的影响。

综合上面两个因素,可以利用组合数来统计方案数。值得注意的是如果每三位的1的位置相同那么要提防填充出相同结果。

时间复杂度$O(n)$

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1020000;
 5 const int mod = 998244353;
 6 
 7 int n;
 8 
 9 int f[maxn][2],g[maxn][2];
10 int pw3[maxn];
11 int c[maxn];
12 
13 int fast_pow(int now,int pw){
14     int ans = 1,dt = now,bit = 1;
15     while(bit <= pw){
16         if(bit & pw) ans = (1ll*ans*dt)%mod;
17         bit <<=1;dt = (1ll*dt*dt)%mod;
18     }
19     return ans;
20 }
21 
22 void work(){
23     if(n == 1) {puts("3");return;}
24     pw3[0] = 1;for(int i=1;i<=n;i++) pw3[i] = 3ll*pw3[i-1]%mod;
25     c[0] = 1;
26     for(int i=1;i<=n;i++){
27         c[i]=(1ll*c[i-1]*(n-i+1))%mod;
28         c[i]=(1ll*c[i]*fast_pow(i,mod-2))%mod;
29     }
30     int sum = fast_pow(pw3[n],n);
31     f[0][1] = 1; g[0][1] = (pw3[n]-3+mod)%mod;
32     f[n][0] = (pw3[n]-3+mod)%mod; g[n][0] = 1;
33     for(int i=1;i<n;i++){
34         f[i][1] = 3ll*c[i]%mod;
35         f[i][0] = (1ll*pw3[i]*c[i])%mod;
36         f[i][0] -= f[i][1]; f[i][0] += mod; f[i][0] %= mod;
37         g[i][0] = pw3[n-i];    g[i][1] = (pw3[n-i]-1+mod)%mod;
38     }
39     for(int i=0;i<=n;i++){
40         g[i][0] = fast_pow(g[i][0],n); g[i][1] = fast_pow(g[i][1],n);
41         int dr = ((i&1)?1:-1);
42         sum += dr*(1ll*g[i][0]*f[i][0])%mod;
43         if(sum >= mod) sum-=mod; if(sum < 0) sum += mod;
44         sum += dr*(1ll*g[i][1]*f[i][1])%mod;
45         if(sum >= mod) sum-=mod; if(sum < 0) sum += mod;
46     }
47     printf("%d",sum);
48     
49 }
50 
51 int main(){
52     scanf("%d",&n);
53     work();
54     return 0;
55 }
点赞
收藏
评论区
推荐文章
kenx kenx
3年前
MySQL查询结果集字符串操作之多行合并与单行分割
前言我们在做项目写sql语句的时候,是否会遇到这样的场景,就是需要把查询出来的多列,按照字符串分割合并成一列显示,或者把存在数据库里面用逗号分隔的一列,查询分成多列呢,常见场景有,文章标签,需要吧查询多个标签合并成一列,等,需要怎么去实现呢,这就涉及到MySQL的字符串操作groupconcat场景再现我想把查询多列数据合并成一列显示用逗号分隔
DaLongggggg DaLongggggg
3年前
python刷题-数列特征
问题描述给出n个数,找出这n个数的最大值,最小值,和。输入格式第一行为整数n,表示数的个数。第二行有n个数,为给定的n个数,每个数的绝对值都小于10000。输出格式输出三行,每行一个整数。第一行表示这些数中的最大值,第二行表示这些数中的最小值,第三行表示这些数的和。样例输入513245样例输出5211数据规模与约定1<n<10000。
Stella981 Stella981
3年前
Spark DataFrame列的合并与拆分
版本说明:Spark2.3.0使用SparkSQL在对数据进行处理的过程中,可能会遇到对一列数据拆分为多列,或者把多列数据合并为一列。这里记录一下目前想到的对DataFrame列数据进行合并和拆分的几种方法。1DataFrame列数据的合并例如:我们有如下数据,想要将三列数据合并为一列,并以“,”分割
Stella981 Stella981
3年前
LeetCode
一目录不折腾的前端,和咸鱼有什么区别目录一目录二题目三解题思路四统计分析五解题套路二题目在一个nm的二维数组中:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。示例
Stella981 Stella981
3年前
Apache POI 合并单元格
合并单元格所使用的方法:sheet.addMergedRegion(CellRangeAddress  cellRangeAddress  );CellRangeAddress  对象的构造方法需要传入合并单元格的首行、最后一行、首列、最后一列。CellRangeAddresscranewCellRangeAddress(0,3,3,
Wesley13 Wesley13
3年前
使用伸缩盒布局创建一个三列布局每一列占用`col
\使用伸缩盒布局创建一个三列布局每一列占用\col{n}\/12份基于父级容器的宽度\Answer设置\.row\类的父级容器为\display:flex;\样式然后使用\flex\缩写形式属性给每一列子元素设置一个\flexgrow\值使得每一列可以按照设置的比例自动协调宽度
Wesley13 Wesley13
3年前
Codevs 1159最大全0子矩阵
题目描述Description在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。输入描述InputDescription输入文件第一行为整数N,其中1<N<2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。输出描述OutputDescription
Stella981 Stella981
3年前
Leet Code 74 Search a 2D Matrix
写一个高效的算法,在m×n的二维矩阵中搜索一个值。矩阵有以下性质:每一行从左到右为升序。每一行的第一个数都比上一行最后一个数大。例如,有以下矩阵:\  \1,  3, 5, 7\,  \10,11,16,20\,  \23,30,34,50\\给定target3,返
Stella981 Stella981
3年前
Python_每日习题_0003_完全平方数
题目一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?程序分析因为168对于指数爆炸来说实在太小了,所以可以直接省略数学分析,用最朴素的方法来获取上限:n0while(n1)2nn<168:n1
Wesley13 Wesley13
3年前
mysql基础(1)
1.常见术语数据库:数据库是一些关联表的集合。.数据表:表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。列:一列(数据元素)包含了相同的数据,例如邮政编码的数据。行:一行(元组,或记录)是一组相关的数据,例如一条用户订阅的数据。冗余:存储两倍数据,冗余可以使系