「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)\) 表示,如果要 ...
随机推荐
- handsontable合并表头
想在页面中做类似excel的操作,发现handsontable符合要求. 然后发现这个文章 http://blog.csdn.net/wynan830/article/details/9054195 ...
- 使用 JS 输出螺旋矩阵
关于螺旋矩阵 这是我曾经遇到过的面试题,在 LeetCode 上找到了题目的原型,难度中等.题目描述如下: 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中 ...
- Django子应用里的通用类混合视图处理
# 子应用的views.py此文件用于编写Web应用视图,处理复杂的业务逻辑 #导入方法视图模板 from django.shortcuts import render #导包 from django ...
- Login Verification CodeForces - 928A (实现)
When registering in a social network, users are allowed to create their own convenient login to make ...
- (七)jdk8学习心得之join方法
七.join方法 1. 作用:将list或者数组按照连接符进行连接,返回一个字符串. 2. 使用方法 1) String.join(“连接符”,数组对象或者list对象) 2) 首先转换成stream ...
- 【学亮编程手记】Spring Cloud三大组件Eureka/Feign/Histrix的原理及使用
- docker企业实战视频教程
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).bare metal. ...
- kettle变量(var变量)
设置变量/set varibale 1.定义变量(子转换): 原始数据 设置获取变量:点击获取字段,自动获取变量名称和字段名称 引用变量: 输出: kettle.properties 文件存储在.ke ...
- mysql和mariadb备份工具xtrabackup和mariabackup(mariadb上版本必须用这个)
简介 xtraBackup(PXB) 工具是 Percona 公司用 perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle).Percona Server ...
- 存储类&作用域&生命周期&链接属性
链接属性 (1)大家知道程序从源代码到最终可执行程序,经历的过程:编译.链接. (2)编译阶段就是把源代码搞成.o目标文件,目标文件里面有很多符号和代码段.数据段.bss段等分段.符号就是编程中的变量 ...