题意

  给你一个 \((k-1)\times (n+1)\) 的 \(01\) 矩阵 \(g\),求满足下列条件的 \(k(k\le 10)\) 进制整数的数量:

    1. 不超过 \(n\) 位且数的最高位非 \(0\)

    2. 没有出现 \(0\)

    3. 对于 \(0\) 以外的数字 \(i\),对于 \(j∈[0,n]\),若 \(g(i,j)=1\),则允许数字 \(i\) 恰好出现 \(j\) 次;若 \(g(i,j)=0\),则不允许数字 \(i\) 恰好出现 \(j\) 次。

  这个问题太简单了,于是有 \(m\) 次修改操作,每次将 \(g(i,j)\) 单点取反。让你求修改前及每次修改操作后的答案之和 \(\mod 786433\)。

  \(786433=2^{18}\times 3 + 1\),是个质数。

  \(k\le 10,\space n\le 14000,\space m\le 200\)

题解

  所以放一个这么明显的 \(\text{NTT}\) 模数是什么意思

  

  前置普及组知识:你有 \(x_1\) 个 \(1\),\(x_2\) 个 \(2\),……,\(x_n\) 个 \(n\),用这 \(x_1+x_2+\cdots+x_n\) 个数构成的不同排列数为 \(\frac{(x_1+x_2+\cdots+x_n)!}{x_1! x_2! \cdots x_n!}\)。

  

  构造指数生成函数 \(f_i(x) = \sum\limits_{j=0}^{n} g(i,j) \frac{x^j}{j!}\),将这 \(k-1\) 个多项式卷积成一个生成函数后,记 \(i\) 次项系数为 \(a_i\),则答案为 \(\sum\limits_{i=1}^n a_i i!\)。

  可以用 \(\text{NTT}\) 在 \(O(nk^2\log (nk))\) 的复杂度内预处理出初始答案。

  

  下面考虑修改。注意到我们只关心所有答案的和,故可以在 \(\text{DFT}\) 意义下直接累加答案,最后再将结果 \(\text{IDFT}\) 回来。

  对于单点修改操作,可以看成是给某个多项式 \(A\) 叠加上一个只有一项系数不为 \(0\) 的多项式 \(B\)。

  因为 \(A\) 正处于点值表示法,所以我们把 \(B\) 也转化成点值表示法(其长度需要扩到与 \(A\) 相等)。这需要 \(O(nk\log(nk))\) 的时间由于只有一项系数不为 \(0\),我们考虑暴力 \(\text{DFT}\)。

  观察指数生成函数 \(\text{NTT}\) 的公式:

  $$y_n = \sum\limits_{i=0}^{d-1}\frac{x_n}{n!}\times (g\frac{p-1}{d}){ni}\mod p$$

  那么之前的多项式 \(B\) 在 \(\text{DFT}\) 后的结果是一个等比数列,故直接对原始多项式叠加一个等比数列即可。

  然而如果直接暴力叠加的话,修改部分的复杂度是 \(O(nmk^2)\)(不过实测能卡过)。

  发现把 \(k-1\) 个 \(\text{DFT}\) 后的多项式放成 \(k-1\) 行,依次对齐每次项,由于点值表示法下,这些多项式卷起来的第 \(i\) 位是这些多项式第 \(i\) 位的乘积,显然只要有一个是 \(0\),这一列就废了。考虑记录 \(\text{DFT}\) 下每一列 \(0\) 的数量以及非 \(0\) 数的乘积,这样每次单点修改时就只需要修改该点所在的一行多项式的信息。

  复杂度 \(O(nk^2\log(nk) + nmk)\)。

#include<bits/stdc++.h>
#define ll long long
#define N 140010
#define mod 786433
#define G 10
#define invG 235930
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
if(f) return x; return 0-x;
}
int Pow(int x, int y){
int ret=1;
while(y){
if(y&1) ret=(ll)ret*x%mod;
x=(ll)x*x%mod;
y>>=1;
}
return ret;
}
struct Poly{
int n,bit,r[N];
void init(int x){
for(n=1,bit=0; n<x; n<<=1,++bit);
for(int i=1; i<n; ++i) r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
//cout<<"n:"<<n<<endl;
}
void dft(int *a, int f){
for(int i=0; i<n; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1; i<n; i<<=1){
int wn = Pow(f==1 ? G : invG, (mod-1)/(i<<1));
for(int j=0; j<n; j+=(i<<1)){
int w=1,x,y;
for(int k=0; k<i; ++k,w=(ll)w*wn%mod)
x=a[j+k], y=(ll)w*a[j+i+k]%mod,
a[j+k]=(x+y)%mod, a[j+i+k]=(x-y+mod)%mod;
}
}
if(f==-1){
int mul=Pow(n,mod-2);
for(int i=0; i<n; ++i) a[i]=(ll)a[i]*mul%mod;
}
}
}NTT;
char c[11][N];
int k,n,m,e[11][N],f[11][N],g[N],ans;
int inv[mod+5],jc[N],jcn[N];
int mul[N],zero_cnt[N];
int main(){
k=read(), n=read(), m=read();
int num=(k-1)*n;
inv[0]=inv[1]=jc[0]=jcn[0]=1;
for(int i=2; i<mod; ++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
for(int i=1; i<=num; ++i) jc[i]=(ll)jc[i-1]*i%mod, jcn[i]=inv[jc[i]];
for(int i=1; i<k; ++i){
scanf("%s",c[i]);
for(int j=0; j<=n; ++j){
e[i][j]=c[i][j]-'0';
f[i][j] = e[i][j] ? jcn[j] : 0;
}
}
NTT.init(num+1);
for(int i=0; i<NTT.n; ++i) mul[i]=1, g[i]=1;
for(int i=1; i<k; ++i){
NTT.dft(f[i],1);
for(int j=0; j<NTT.n; ++j){
g[j]=(ll)g[j]*f[i][j]%mod;
if(!f[i][j]) ++zero_cnt[j];
else mul[j]=(ll)mul[j]*f[i][j]%mod;
//cout<<f[i][j]<<endl;
}
}
//for(int i=0; i<NTT.n; ++i) cout<<g[i]<<endl;
int x,y;
while(m--){
x=read(), y=read();
e[x][y]^=1;
//for(int i=0; i<NTT.n; ++i) cout<<mul[i]<<' '<<zero_cnt[i]<<endl;
for(int i=0; i<NTT.n; ++i){
if(f[x][i]) mul[i]=(ll)mul[i]*inv[f[x][i]]%mod;
else --zero_cnt[i];
}
int val=jcn[y], tol=Pow(G,(mod-1)/NTT.n*y%(mod-1));
if(!e[x][y]) val=mod-val;
for(int i=0; i<NTT.n; ++i){
f[x][i]=(f[x][i]+val)%mod;
//cout<<f[x][i]<<endl;
val=(ll)val*tol%mod;
}
for(int i=0; i<NTT.n; ++i){
if(f[x][i]) mul[i]=(ll)mul[i]*f[x][i]%mod;
else ++zero_cnt[i];
if(!zero_cnt[i]) g[i]=(g[i]+mul[i])%mod;
}
}
NTT.dft(g,-1);
for(int i=1; i<=num; ++i){
ans=(ans+(ll)g[i]*jc[i]%mod)%mod;
//cout<<f[k-1][i]<<' '<<jc[i]<<endl;
}
cout<<ans<<endl;
return 0;
}
/*
3 2 0
101
010 3 2 0
111
010 3 2 0
110
010 3 2 1
101
010
1 1
*/

【hdu 6067】Big Integer的更多相关文章

  1. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  2. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  3. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

  4. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

  5. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

  6. 【HDU 5145】 NPY and girls(组合+莫队)

    pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Other ...

  7. 【hdu 2955】Robberies

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...

  8. 【hdu 5996】dingyeye loves stone

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s) ...

  9. 【hdu 2486】A simple stone game

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...

随机推荐

  1. Pythoncookbook(数据结构与算法)在字典中将键映射到多个值上的方法

    Python cookbook(数据结构与算法)在字典中将键映射到多个值上的方法 本文实例讲述了Python在字典中将键映射到多个值上的方法.分享给大家供大家参考,具体如下: 问题:一个能将键(key ...

  2. C基础知识(2):变量&常量的定义和声明

    变量定义和声明 (1) 使用int,char等类型符定义变量 使用int,char等类型符定义变量时,不管有没有指定初始值,都就已经建立了存储空间(开辟内存).内存寻址由大到小,优先分配内存地址比较大 ...

  3. k8s 删除ns 卡住的解决办法

    在某些情况下,在k8s中会无法删除某个namespace,它会一直卡在terminating状态下.解决这个问题的步骤为: kubectl api-resources --verbs=list --n ...

  4. 解决win10 windows mobile 设备中心无法打开问题,MC3200无法连上win10问题

    1.下载高版本的安装包 从微软官方下载:https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=3182 2.  运行service ...

  5. 积累-T

    emmm,各种知识点都有吧,主要方便自己记 随机修改网页图标 <script> var image=new Array(3); image.length=3; image[1]=" ...

  6. Tensorflow实战第十课(RNN MNIST分类)

    设置RNN的参数 我们本节采用RNN来进行分类的训练(classifiction).会继续使用手写数据集MNIST. 让RNN从每张图片的第一行像素读到最后一行,然后进行分类判断.接下来我们导入MNI ...

  7. 【DSP开发】HyperLink 编程和性能考量

    冯华亮/Brighton Feng---Communication Infrastructure 摘要 HyperLink 为两个 KeyStone 架构 DSP 之间提供了一种高速,低延迟,引脚数量 ...

  8. sqlalchemy orm 层面删除数据注意

    #encoding: utf-8 from sqlalchemy import create_engine,Column,Integer,String,Float,func,and_,or_,Text ...

  9. Duilib的多级菜单实现(网易云信版本)

    完整代码见:https://github.com/netease-im/NIM_Duilib_Framework/tree/master/ui_components/menu 核心代码: ui_men ...

  10. [xpath] 定位中starts-with、contains和text()的用法

    starts-with 顾名思义,匹配一个属性开始位置的关键字 contains 匹配一个属性值中包含的字符串 text() 匹配的是显示文本信息,此处也可以用来做定位用 eg //input[sta ...