「HNOI 2019」白兔之舞
一道清真的数论题
题解
考虑$ n=1$的时候怎么做
设$ s$为转移的方案数
设答案多项式为$\sum\limits_{i=0}^L (sx)^i\binom{L}{i}=(sx+1)^L$
答案相当于这个多项式模$ k$的各项系数的和
发现这和LJJ学二项式定理几乎一模一样
然而直接搞是$ k^2$的,无法直接通过本题
以下都用$ w$表示$ k$次单位根
设$ F_i$为次数模$ k$为$ i$的项的系数和
单位根反演一下得到$F(i)=\sum\limits_{j=0}^{k-1}w^{-ij}(sw^j+1)^L$
组合数有个非常优美的性质
$$ij=\binom{i+j}{2}-\binom{i}{2}-\binom{j}{2}$$
推波式子
$$
\begin{aligned}
F(i)&=\sum_{j=0}^{k-1}w^{-ij}(sw^j+1)^L\\
&=\sum_{j=0}^{k-1}w^{\binom{i}{2}+\binom{j}{2}-\binom{i+j}{2}}(sw^j+1)^L\\
&=w^\binom{i}{2}\sum_{j=0}^{k-1}w^{-\binom{i+j}{2}}w^\binom{j}{2}(sw^j+1)^L\\
\end{aligned}
$$
发现这是一个差卷积的形式
扔一个$ MTT$上去就能拿那$ 40$分了
考虑$ n>1$的情况
相当于把$ s$从一个数变成了矩阵,把$ 1$变成单位矩阵
$ (sw^j+1)^L$这个矩阵我们只需要关注一个位置上的值
因此可以乘出来然后取[x][y]这个位置上的数即可
这样就可以通过此题
复杂度:大常数单 $\log$
代码
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,cnt,p,L;
int w[],val[];
int f[],g[],F[];
int ksm(int x,int y=p-){
int ans=;
for(;y;y>>=,x=1ll*x*x%p)if(y&)ans=1ll*ans*x%p;
return ans;
}
struct mat{
ll a[][];
void print(){
for(rt i=;i<n;i++)for(rt j=;j<n;j++)cout<<a[i][j]<<" \n"[j==n-];
}
inline mat operator*(const mat s)const{
mat ret={};
for(rt i=;i<n;i++)
for(rt k=;k<n;k++)
for(rt j=;j<n;j++)
(ret.a[i][j]+=a[i][k]*s.a[k][j]);
for(rt i=;i<n;i++)for(rt j=;j<n;j++)ret.a[i][j]%=p;
return ret;
}
mat operator*(const int s)const{
mat ret;
for(rt i=;i<n;i++)
for(rt j=;j<n;j++)
ret.a[i][j]=a[i][j]*s%p;
return ret;
}
mat operator+(const mat s)const{
mat ret;memset(ret.a,,sizeof(ret.a));
for(rt i=;i<n;i++)
for(rt j=;j<n;j++)
ret.a[i][j]=(a[i][j]+s.a[i][j])%p;
return ret;
} }I,zy;
mat ksm(mat x,int y){
mat ans=I;
for(;y;y>>=,x=x*x)if(y&)ans=ans*x;
return ans;
}
int V(int x){
return 1ll*x*(x-)/%k;
}
const double PI=acos(-1.0);
struct cp{
double x,y;
cp operator +(const cp &s)const{return {x+s.x,y+s.y};}
cp operator -(const cp &s)const{return {x-s.x,y-s.y};}
cp operator *(const cp &s)const{return {x*s.x-y*s.y,x*s.y+y*s.x};}
}W[][<<],A[],B[],C[],D[];
int R[];
void FFT(const int n,cp *A){
for(rt i=;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
for(rt j=;j<n;j+=){
const cp x=A[j],y=A[j+];
A[j]=x+y,A[j+]=x-y;
}
for(rt i=,s=;i<n;i<<=,s++)
for(rt j=;j<n;j+=i<<)
for(rt k=;k<i;k+=){
cp x=A[j+k],y=W[s][k]*A[i+j+k];
A[j+k]=x+y;A[i+j+k]=x-y;
x=A[j+k+],y=W[s][k+]*A[i+j+k+];
A[j+k+]=x+y;A[i+j+k+]=x-y;
}
}
int yg(int n){
for(rt i=;i<=n;i++){
for(rt j=;j*j<=n;j++)if((n-)%j==)
if(ksm(i,(n-)/j)==)goto end;
return i;end:;
}
}
void subtask(){
w[]=;w[]=ksm(yg(p),(p-)/k);
for(rt i=;i<k;i++)w[i]=1ll*w[i-]*w[]%p;mat s=zy;
for(rt i=;i<k;i++){
g[i]=ksm(s*w[i]+I,L).a[x-][y-]*w[V(i)]%p;
}
for(rt i=;i<k+k;i++)f[i]=w[(k-V(i))%k];
for(rt i=;i<k/;i++)swap(g[i],g[k-i]); n=k+k-;m=k;
int lim=;while(lim<=n+m)lim<<=;
for(rt i=;(<<i)<lim;i++){
W[i][]={,};
W[i][]={cos(PI/(<<i)),sin(PI/(<<i))};
for(rt j=;j<<<i;j++)
if(j%==)W[i][j]={cos(PI*j/(<<i)),sin(PI*j/(<<i))};
else W[i][j]=W[i][j-]*W[i][];
} for(rt i=;i<=n;i++){
A[i].x=f[i]>>;
A[i].y=f[i]&;
}
for(rt i=;i<=m;i++){
B[i].x=g[i]>>;
B[i].y=g[i]&;
}
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
FFT(lim,A);FFT(lim,B);
for(rt i=;i<lim;i++){
const int pl=(lim-)&(lim-i);
const cp ca={A[pl].x,-A[pl].y},cb={B[pl].x,-B[pl].y};
const cp a=(A[i]+ca)*(cp){0.5,},b=(A[i]-ca)*(cp){,-0.5},
c=(B[i]+cb)*(cp){0.5,},d=(B[i]-cb)*(cp){,-0.5};
C[pl]=a*c+a*d*(cp){,};D[pl]=b*c+b*d*(cp){,};
}
FFT(lim,C);FFT(lim,D);
for(rt i=k;i<k+k;i++){
const int vv=1ll*w[V(i-k)]*ksm(k,p-)%p;
ll a=C[i].x/lim+0.5,b=C[i].y/lim+0.5,c=D[i].x/lim+0.5,d=D[i].y/lim+0.5;
a=((a%p)<<)+(((b+c)%p)<<)+d;a=(a%p+p)%p;
writeln(1ll*a*vv%p);
}
exit();
}
int jc[],njc[],inv[],ff[][],ans[];
int c(int x,int y){
return 1ll*jc[x]*njc[y]%p*njc[x-y]%p;
}
void bl(){
for(rt i=;i<;i++)jc[i]=njc[i]=inv[i]=;
for(rt i=;i<=L;i++){
jc[i]=1ll*jc[i-]*i%p;
inv[i]=1ll*inv[p%i]*(p-p/i)%p;
njc[i]=1ll*njc[i-]*inv[i]%p;
}
ff[][x-]=;if(x==y)ans[]=;
for(rt i=;i<=L;i++)
for(rt j=;j<n;j++){
for(rt k=;k<n;k++)
(ff[i][j]+=1ll*zy.a[k][j]*ff[i-][k]%p)%=p;
if(j==y-)(ans[i%k]+=1ll*ff[i][j]*c(L,i)%p)%=p;
}
for(rt i=;i<k;i++)writeln(ans[i]);exit();
}
int main(){
cin>>n>>k>>L>>x>>y>>p;
for(rt i=;i<n;i++)
for(rt j=;j<n;j++)
cin>>zy.a[i][j];
if(L<=)bl();
for(rt i=;i<n;i++)I.a[i][i]=;
subtask();
return ;
}
「HNOI 2019」白兔之舞的更多相关文章
- LOJ#3054. 「HNOI 2019」鱼
LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...
- Solution -「HNOI 2019」「洛谷 P5293」白兔之舞
\(\mathcal{Description}\) Link. 不想概括题意.jpg \(\mathcal{Solution}\) 定义点集 \(S_c=\{(u,v)|v=c\}\):第 ...
- Loj 3058. 「HNOI2019」白兔之舞
Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...
- 「WC 2019」数树
「WC 2019」数树 一道涨姿势的EGF好题,官方题解我并没有完全看懂,尝试用指数型生成函数和组合意义的角度推了一波.考场上只得了 44 分也暴露了我在数数的一些基本套路上的不足,后面的 \(\ex ...
- #3146. 「APIO 2019」路灯
#3146. 「APIO 2019」路灯 题目描述 一辆自动驾驶的出租车正在 Innopolis 的街道上行驶.该街道上有 \(n + 1\) 个停车站点,它们将街道划分成了 \(n\) 条路段.每一 ...
- #3145. 「APIO 2019」桥梁
#3145. 「APIO 2019」桥梁 题目描述 圣彼得堡市内所有水路长度总和约 282 千米,市内水域面积占城市面积的 7%.--来自维基百科 圣彼得堡位于由 \(m\) 座桥梁连接而成的 \(n ...
- #3144. 「APIO 2019」奇怪装置
#3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个 ...
- 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)
[题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...
- 「loj3058」「hnoi2019」白兔之舞
题意 有一个\((L+1)*n\) 的网格图,初始时白兔在\((0,X)\) , 每次可以向横坐标递增,纵坐标随意的位置移动,两个位置之间的路径条数只取决于纵坐标,用\(w(i,j)\) 表示,如果要 ...
随机推荐
- 简介---linux内核态和用户态
内核态:进程运行在内核空间:管理系统的所有资源,比如读写磁盘文件,分配回收内存,从网络接口读写数据等等 用户态:进程运行在用户空间.比如一些应用程序 内核如何调用硬件资源的:内核空间中的代码控制了硬件 ...
- springmvc源码分析——入门看springmvc的加载过程
本文将分析springmvc是如何在容器启动的时候将各个模块加载完成容器的创建的. 我知道在web.xml文件中我们是这样配置springmvc的: 可以看到,springmvc的核心控制器就是Dis ...
- 解决 golang unrecognized import path "golang.org/x" 之类错误的一种尝试
如果使用的开发IDE是goland,那么 打开 FILE -> setting -> Go Modules 选项 ,在proxy 选项上填写 "https://goproxy.i ...
- 类Object
Object概述 java.lang.Object类是Java语言中的根类,即所有类的父类.它中描述的所有方法子类都可以使用.在对象实例化的时候,最终找的父类就是Object. 如果一个类没有特别指定 ...
- 将WTL应用向导添加到VS2019
WTL 简介 WTL 全称是 Windows Template Library,像 MFC 一样使用 C++ 的面向对象技术对 Win32 接口进行了封装,使之便于开发 Windows 程序.相对于 ...
- 通过java代码执行Linux命令查询声卡和显卡 型号
package test; import java.io.BufferedReader; import java.io.InputStreamReader; public class ExcuteLi ...
- 【刷题】Git知识点
参考:学习总结之Git学习-总 1-origin是什么? 答:origin 是默认的远程版本库名称,可以在 .git/config 之中进行修改.在默认情况下,origin指向的就是你本地的代码库托管 ...
- js 前端常用排序算法总结
(冒泡排序.快排顺序.选择排序.插入排序.归并排序) 下面是前端比较常用的五个算法demo: 冒泡算法:比较两个相邻的数值,if第一个>第二个,交换他们的位置元素项向上移动至正确的顺序. fun ...
- Windows下安装配置MongoDB
Windows下安装配置MongoDB 一,介绍 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB ...
- 1、Mysql无法创建外键的原因 2、MySql 外键约束 之CASCADE、SET NULL、RESTRICT、NO ACTION分析和作用
在Mysql中创建外键时,经常会遇到问题而失败,这是因为Mysql中还有很多细节需要我们去留意,我自己总结并查阅资料后列出了以下几种常见原因. 1. 两个字段的类型或者大小不严格匹配.例如,如果一个 ...