[loj2504]小H爱染色
以下考虑直接对所有$F(A)$求和,并给出两种做法——
做法1:
枚举答案$A$,对应方案数为${n-A\choose m}^{2}-{n-A-1\choose m}^{2}$,即答案为$\sum_{i=0}^{n-1}({n-i\choose m}^{2}-{n-i-1\choose m}^{2})F(i)$
记$G(n)=\sum_{i=0}^{n-1}{n-i\choose m}^{2}F(i)$,有$ans=G(n)-G(n-1)$,以下仅考虑求$G(n)$
不难证明$G(n)$是一个关于$n$的不超过$3m+1$次的多项式(将$3m$次多项式求前缀和即为$3m+1$次),更具体的,我们只需要求出$G(0),G(1),...,G(3m+1)$就可以确定$G(n)$
根据拉格朗日差值,维护$o(m)$以内的阶乘即逆元就可以$o(m)$的插出一个位置上的值
接下来,我们考虑怎么求出$G(i)$($0\le i\le 3m+1$):
先考虑求出所有$F(i)$($0\le i\le 3m+1$)的值,单次$o(m)$总复杂度即为$o(m^{2})$,无法通过
考虑拉格朗日插值法具体的式子,即为$F(i)=\sum_{j=0}^{m}F(j)\prod_{0\le k\le m,k\ne j}\frac{i-k}{j-k}$
预处理出$H_{j}=F(j)\prod_{0\le k\le m,k\ne j}\frac{1}{j-k}$,则$F(i)=\sum_{j=0}^{m}H_{j}\prod_{0\le k\le m,k\ne j}(i-k)$
当$0\le i\le m$,直接可得结果,那么假设$m<i\le 3m+1$,则$\prod_{0\le k\le m,k\ne j}(i-k)=\frac{\prod_{0\le k\le m}(i-k)}{i-j}$
简单化简,即$F(i)=\prod_{j=0}^{m}(i-j)\sum_{j=0}^{m}\frac{H_{j}}{i-j}$,前者利用逆元即可以从上一个$o(1)$算出,后者考虑$H_{i}$的生成函数$H(x)=\sum_{i=0}^{m}H_{i}x^{i}$和$H'(x)=\sum_{i=1}^{3m+1}\frac{x^{i}}{i}$,那么即$(H\times H')(x)[x^{i}]$
接下来,对于$G(i)=\sum_{j=0}^{i-1}{i-j\choose m}^{2}F(j)$,考虑$F(j)$的生成函数$F'(x)=\sum_{i=0}^{3m+1}F(i)x^{i}$以及$H''(x)=\sum_{i=1}^{3m+1}{i\choose m}^{2}x^{i}$,有$G(i)=(F'\times H'')(x)[x^{i}]$
用ntt计算多项式乘法,复杂度为$o(m\log m)$
最后$G(n)=\sum_{i=0}^{3m+1}G(i)\prod_{0\le j\le 3m+1,j\ne i}\frac{n-j}{i-j}$,$o(m)$差值即可
但这一做法的常数较大,我写不过去QAQ
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N (1<<23)
4 #define mod 998244353
5 int n,m,t,inv[N],Inv[N],rev[N],a[N],b[N],f[N];
6 int ksm(int n,int m){
7 n=(n+mod)%mod;
8 int s=n,ans=1;
9 while (m){
10 if (m&1)ans=1LL*ans*s%mod;
11 s=1LL*s*s%mod;
12 m>>=1;
13 }
14 return ans;
15 }
16 void ntt(int *a,int p){
17 for(int i=0;i<N;i++)
18 if (i<rev[i])swap(a[i],a[rev[i]]);
19 for(int i=2;i<=N;i<<=1){
20 int s=ksm(3,(mod-1)/i);
21 if (p)s=ksm(s,mod-2);
22 for(int j=0;j<N;j+=i)
23 for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){
24 int x=a[j+k],y=1LL*a[j+k+(i>>1)]*ss%mod;
25 a[j+k]=(x+y)%mod;
26 a[j+k+(i>>1)]=(x+mod-y)%mod;
27 }
28 }
29 if (p){
30 int s=ksm(N,mod-2);
31 for(int i=0;i<N;i++)a[i]=1LL*a[i]*s%mod;
32 }
33 }
34 int get(int n){
35 if (n<=t)return f[n];
36 int ss=1,ans=0;
37 for(int i=0;i<=t;i++)ss=1LL*ss*(n-i)%mod;
38 for(int i=0;i<=t;i++){
39 int s=1LL*Inv[t-i]*Inv[i]%mod;
40 if ((t-i)&1)s=mod-s;
41 s=1LL*s*ss%mod*ksm(n-i,mod-2)%mod;
42 ans=(ans+1LL*f[i]*s)%mod;
43 }
44 return ans;
45 }
46 int main(){
47 scanf("%d%d",&n,&m);
48 t=3*m+1;
49 for(int i=0;i<=m;i++)scanf("%d",&f[i]);
50 inv[0]=inv[1]=Inv[0]=1;
51 for(int i=2;i<=t;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
52 for(int i=1;i<=t;i++)Inv[i]=1LL*Inv[i-1]*inv[i]%mod;
53 for(int i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)+((i&1)*(N>>1));
54 for(int i=0;i<=m;i++){
55 int s=1LL*Inv[m-i]*Inv[i]%mod;
56 if ((m-i)&1)s=mod-s;
57 a[i]=1LL*s*f[i]%mod;
58 }
59 for(int i=1;i<=t;i++)b[i]=inv[i];
60 ntt(a,0);
61 ntt(b,0);
62 for(int i=0;i<N;i++)a[i]=1LL*a[i]*b[i]%mod;
63 ntt(a,1);
64 int s=1;
65 for(int i=1;i<=m;i++)s=1LL*s*i%mod;
66 for(int i=m+1;i<=t;i++){
67 s=1LL*s*inv[i-m-1]%mod*i%mod;
68 f[i]=1LL*a[i]*s%mod;
69 }
70 memset(a,0,sizeof(a));
71 s=1;
72 for(int i=m;i<=t;i++){
73 a[i]=1LL*s*s%mod;
74 s=1LL*s*(i+1)%mod*inv[i-m+1]%mod;
75 }
76 ntt(a,0);
77 ntt(f,0);
78 for(int i=0;i<N;i++)f[i]=1LL*f[i]*a[i]%mod;
79 ntt(f,1);
80 printf("%d",(get(n)-get(n-1)+mod)%mod);
81 }
做法2:
考虑$F(x)=1$的情况,由于$F(A)=1$,答案即为${n\choose m}^{2}$
当然,也可以枚举最终染色的球的数量$k$,对应方案数为${n\choose k}{k\choose m}{m\choose 2m-k}$(最后一个是$m$是因为第二次染色重复只能与第一次重复,内部不能重复),复杂度为$o(m)$
(由于以下还会使用${k\choose m}{m\choose 2m-k}$,将之记作$H_{k}$)
这一做法看上去没有什么意义,但其提示我们具体的位置是不好枚举的,要考虑个数,也就是要让$F(x)$与位置无关(如$F(x)=1$就与位置无关)
考虑$F(x)=x$的情况,构造$A$的组合意义:在两次染色完毕后,再染一个球,且这个球必须是$A$之前的球,那么第三次染色方案数恰好为$A$,三次染色的总方案数即为答案
枚举这三次染色所染的球数量$k+1$,类似的方案数即为${n\choose k+1}H_{k}$
考虑$F(x)=x^{c}$的情况,构造$A^{c}$的组合意义:在两次染色完毕后,再染$c$个球,允许内部重复但同样必须是$A$之前的球的方案数,同样这三次染色的总方案数即为答案
枚举这三次染色所染的球数量$k+t$,前半部分相同为${n\choose k+t}H_{k}$,下面考虑最后$t$个球如何染色
这是一个可以容斥的问题,即枚举强制不能染色的位置个数$i$,即$\sum_{i=0}^{t}(-1)^{i}{t\choose i}(t-i)^{c}$
为了让其可以计算,将组合数展开,即$t!\sum_{i=0}^{t}\frac{(-1)^{i}}{i!}\cdot \frac{(t-i)^{c}}{(t-i)!}$
这又是一个ntt的形式,即$H_{1}(x)=\sum_{i=0}^{m}\frac{(-1)^{i}}{i!}x^{i}$和$H_{2}(x)=\sum_{i=0}^{m}\frac{i^{c}}{i!}x^{i}$,那么$(H_{1}\times H_{2})(x)[x^{i}]$即为$t=i$时除以$t!$的结果,将其乘上$t!$并记作$G_{t}$
之后又是一个$G_{t}$和$H_{k}$的卷积,即$G(x)=\sum_{i=0}^{m}G_{i}x^{i}$以及$H(x)=\sum_{i=m}^{2m}H_{i}x^{i}$,那么$(H\times G)(x)[x^{i}]$即为$k+t=i$时的答案,再乘上${n\choose k+t}$后相加即可
当$F(x)$为普通多项式时,不难发现每一次可以独立,且$H$不变,根据卷积的分配律,可以将所有$G_{i}$相加后做一次,即$G_{i}=\sum_{i=0}^{t}(-1)^{i}{t\choose i}F(t-i)$
类似的构造$H_{2}(x)=\sum_{i=0}^{m}\frac{F(i)}{i!}x^{i}$,求出$G_{i}$后与上面的做法相同
两次ntt即可,时间复杂度为$o(m\log m)$,由于此时多项式次数变为$2m+m$次,常数更小,可以通过
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N (1<<22)
4 #define mod 998244353
5 int n,m,ans,fac[N],inv[N],rev[N],a[N],b[N];
6 int c(int n,int m){
7 if (n<m)return 0;
8 return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
9 }
10 int ksm(int n,int m){
11 n=(n+mod)%mod;
12 int s=n,ans=1;
13 while (m){
14 if (m&1)ans=1LL*ans*s%mod;
15 s=1LL*s*s%mod;
16 m>>=1;
17 }
18 return ans;
19 }
20 void ntt(int *a,int p){
21 for(int i=0;i<N;i++)
22 if (i<rev[i])swap(a[i],a[rev[i]]);
23 for(int i=2;i<=N;i<<=1){
24 int s=ksm(3,(mod-1)/i);
25 if (p)s=ksm(s,mod-2);
26 for(int j=0;j<N;j+=i)
27 for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){
28 int x=a[j+k],y=1LL*a[j+k+(i>>1)]*ss%mod;
29 a[j+k]=(x+y)%mod;
30 a[j+k+(i>>1)]=(x+mod-y)%mod;
31 }
32 }
33 if (p){
34 int s=ksm(N,mod-2);
35 for(int i=0;i<N;i++)a[i]=1LL*a[i]*s%mod;
36 }
37 }
38 int main(){
39 scanf("%d%d",&n,&m);
40 for(int i=0;i<=m;i++)scanf("%d",&a[i]);
41 fac[0]=inv[0]=inv[1]=1;
42 for(int i=1;i<=3*m;i++)fac[i]=1LL*fac[i-1]*i%mod;
43 for(int i=2;i<=3*m;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
44 for(int i=1;i<=3*m;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod;
45 for(int i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)+((i&1)*(N>>1));
46 for(int i=0;i<=m;i++){
47 a[i]=1LL*a[i]*inv[i]%mod;
48 b[i]=inv[i];
49 if (i&1)b[i]=mod-b[i];
50 }
51 ntt(a,0);
52 ntt(b,0);
53 for(int i=0;i<N;i++)a[i]=1LL*a[i]*b[i]%mod;
54 ntt(a,1);
55 memset(b,0,sizeof(b));
56 for(int i=1;i<=2*m;i++){
57 if (i>m)a[i]=0;
58 else a[i]=1LL*fac[i]*a[i]%mod;
59 b[i]=1LL*c(i,m)*c(m,2*m-i)%mod;
60 }
61 ntt(a,0);
62 ntt(b,0);
63 for(int i=0;i<N;i++)a[i]=1LL*a[i]*b[i]%mod;
64 ntt(a,1);
65 int s=1;
66 for(int i=0;i<=3*m;i++){
67 ans=(ans+1LL*a[i]*s%mod*inv[i])%mod;
68 s=1LL*s*(n-i)%mod;
69 }
70 printf("%d",ans);
71 }
[loj2504]小H爱染色的更多相关文章
- hihocoder 1347 小h的树上的朋友
传送门 时间限制:18000ms单点时限:2000ms内存限制:512MB 描述 小h拥有$n$位朋友.每位朋友拥有一个数值$V_i$代表他与小h的亲密度.亲密度有可能发生变化.岁月流逝,小h的朋友们 ...
- 【渗透笔记】拿下某小H网的全过程
自从班上A片小王子的7个T资源被封了以后,本小白为造福全班同学,尝试拿下个小H网,先用webrobot搜某些只有小H网才会出现的关键词 本以为直接导出放御剑里跑就行了,然并软.于是用awvs扫了一下, ...
- 一个简洁的小H车调运模型
一个简洁的小H车调运模型 不久前, 帝都B城市到处都是小H车, 理想的小H车应该是布朗运动\均匀分布,可是现实上它们就是不均匀.于是有如下问题: 观察帝都 HD区SY村区域,将其划分成10个用车点,用 ...
- 小H和密码
链接:https://www.nowcoder.com/acm/contest/72/B来源:牛客网 题目描述 小H在击败怪兽后,被一个密码锁挡住了去路 密码锁由N个转盘组成,编号为1 ...
- acdream 1725 哗啦啦的小彭玉染色问题 离散化并查集
哗啦啦的小彭玉染色问题 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acdream.info/problem?pid=1725 Descri ...
- 【Wannafly挑战赛10 - B】小H和密码(DP)
试题链接:https://www.nowcoder.com/acm/contest/72/B 题目描述 小H在击败怪兽后,被一个密码锁挡住了去路 密码锁由N个转盘组成,编号为1~N,每 ...
- BZOJ1505: [NOI2004]小H的小屋
BZOJ1505: [NOI2004]小H的小屋 Description 小H发誓要做21世纪最伟大的数学家.他认为,做数学家与做歌星一样,第一步要作好包装,不然本事再大也推不出去. 为此他决定先在自 ...
- hihocoder-1347 小h的树上的朋友(lca+线段树)
题目链接: 小h的树上的朋友 时间限制:18000ms 单点时限:2000ms 内存限制:512MB 描述 小h拥有n位朋友.每位朋友拥有一个数值Vi代表他与小h的亲密度.亲密度有可能发生变化. 岁月 ...
- Wannafly挑战赛10:A题:小H和迷宫
题目描述 小H陷入了一个迷宫中,迷宫里有一个可怕的怪兽,血量有N点,小H有三瓶魔法药水,分别可以使怪兽损失a%.b%.c%的血量(之后怪兽的血量会向下取整),小H想合理地运用这三瓶药水,使 ...
随机推荐
- mybatis 配置问题查找
mybatis配置问题记录 org.apache.ibatis.binding.BindingException: Type interface com.xx.dao.UserDao(自己项目的文件) ...
- DL4J实战之四:经典卷积实例(GPU版本)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- FastAPI 学习之路(七)字符串的校验
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...
- 安装早期老版本 Visual Studio
安装早期老版本 Visual Studio https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/
- 小甲鱼零基础学python第25讲课后习题动手练习--通讯录
小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...
- Golang通脉之切片
因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性. func arraySum(x [3]int) int{ sum := 0 for _, v := range x{ su ...
- selenium3 利用cookie实现免登陆
1.首先访问要操作的页面 2.登陆一次,使用Fiddle等工具抓取出cookie 3.按照如下代码,即可成功登陆 from selenium import webdriver url = " ...
- 微软Windows11安卓子系统已支持运行APK 应用(附手把手详细安装攻略)怎么安装安卓/如何安装安卓应用/支持多窗口多任务
10 月 21 日消息,微软博客宣称,Windows 11 上 安卓子系统运行 Android 应用程序的第一个预览版现已提供给美国 Beta 频道的 Windows 内部人员.但现在通过教程 ...
- 【UE4 C++ 基础知识】<4> 枚举 Enum、结构体 Struct
枚举 UENUM宏搭配BlueprintType可以将枚举暴露给蓝图,不使用的话,仅能在C++使用 //定义一个原生enum class enum class EMyType { Type1, Typ ...
- Linux中检查字符串是否为合法IP地址的shell脚本
#!/bin/bash #判断IP地址是否为有效IP CHKECK_IP () { CHECK_STEP1=`echo $1 | awk -F"." '{print NF}'` i ...