(以下以$B$为进制,$m$为幂次,$n=B^{m}$)

定义$\oplus$为$k$进制下不进位加法,$\otimes$为$\oplus$卷积

令$f_{i,j}$表示前$i$个数的$\oplus$之和为$j$的子序列数,再令$g_{i,j}=[j=0]+[j=a_{i}]$($a_{i}$为给定序列),则$f_{i}=f_{i-1}\otimes g_{i}$

类似uoj272,但以该题复杂度计算时间复杂度显然是不对的

根据$g_{i,j}$的式子,不难发现将其做了DFT后的结果显然恰好就是矩阵$A$的第0行加第$a_{i}$行

直接考虑最终将每一个$g_{i}$的DFT对应位置相乘后第$j$个位置的值,即$ans_{j}=\prod_{i=1}^{n}(A_{0,j}+A_{a_{i},j})$

不难发现$A_{i,j}=\omega^{k}$(指存在$k$,其中$0\le k<B$),我们如果能知道$A_{a_{i},j}$中每一个$k$出现了多少次,再使用快速幂来计算,就可以做到$o(B\log_{2}n)$的复杂度了

更具体的,用$f_{i,j}$表示有多少个$k$满足$A_{a_{k},i}=\omega^{j}$,答案即$ans_{j}=\prod_{i=0}^{B-1}(1+\omega^{i})^{f_{j,i}}$($A_{0,j}=1$)

如何求出$f_{i,j}$,其并不容易递推,考虑这样一个构造:对于每一个$i$,求出$f_{i}$这个长度为$B$的序列DFT的结果,再用IDFT即求出$f_{i,j}$

考虑这个DFT结果的第$k$个数,即$\sum_{l=0}^{B-1}f_{i,l}A_{l,k}=\sum_{l=0}^{B-1}f_{i,l}(\omega^{l})^{k}=\sum_{l=0}^{n-1}(A_{a_{l},i})^{k}$

再构造一个$C_{i}=\sum_{j=0}^{n-1}[a_{j}=i]$,那么对$C$做DFT后的第$i$项即为$\sum_{j=0}^{n-1}C_{j}A_{j,i}=\sum_{j=0}^{n-1}A_{a_{j},i}$

其实这两个式子很接近,只需要让每一个$A_{i,j}$都变为其$k$次幂即可

注意到我们能快速计算DFT依赖于第二个性质($A_{i,j}=A_{\lfloor\frac{i}{B}\rfloor,\lfloor\frac{j}{B}\rfloor}A_{i\ mod\ B,j\ mod\ B}$),而在这个性质下,让每一个$A_{i,j}$都变为其$k$次幂等价于构造$A$左上角的$B\times B$的部分为$A_{i,j}=\omega^{ijk}$

具体来说,分为以下四个步骤:

1.对$C$做$B$次DFT,每一次DFT的$A$矩阵不同,第$k(0\le k<B)$次DFT的$A_{i,j}=\omega^{ijk}(0\le i,j<B)$,这里的时间复杂度是$o(mB^{m+4})$(由于两数相乘复杂度也为$o(B^{2})$,一次DFT复杂度为$o(mB^{m+3})$)

2.对于第一步中第$i$次DFT结果的第$j$项,恰好就是$f_{j}$(这是一个长为$B$的数列)做DFT后的第$i$项,换言之我们得到了每一个$f_{j}$做DFT后的结果,做$n$次$B^{4}$的IDFT即可,复杂度为$o(B^{m+4})$

3.得到$f_{i,j}$后,直接根据$ans_{j}=\prod_{i=0}^{B-1}(1+\omega^{i})^{f_{j,i}}$计算出$ans_{j}$,通过快速幂来优化,那么求一个$ans_{j}$的时间复杂度为$o(B^{3}\log_{2}n)$,总复杂度即$o(B^{m+3}\log_{2}n)$

4.求出$ans_{j}$再做一次IDFT即为答案,时间复杂度为$o(mB^{m+3})$

最终总复杂度为$o((m+\log_{2}n)B^{m+4})$,可以通过

另外关于数值的表示,在平常递归时先使用$\sum_{i=0}^{B-1}a_{i}\omega^{i}$来表示,根据$\omega^{B}=1$可以对其封闭运算,当我们可以证明某一个数为实数且需要得到该值时,通过如下方式降幂,然后$\omega^{0}$系数即为答案

降幂的需要对$B$分类:

1.若$B=5$,将$\omega^{4}$利用$\sum_{i=0}^{4}\omega^{i}=\frac{1-\omega^{5}}{1-\omega}=0$来降幂

2.若$B=6$,根据$\omega^{3}=-1$来降幂,首先得到$\omega^{i}=-\omega^{i-\frac{B}{2}}$来将$i$次项($\frac{B}{2}\le i<B$)降幂,再利用$\sum_{i=0}^{2}(-\omega)^{i}=\frac{1-(-\omega)^{3}}{1+\omega}=0$来降$\omega^{2}$

关于这个降幂的正确性(也就是之后高次项不能将虚数部分抵消)不会证,但可以发现其等价于不能再次进行降幂,之后(观察)发现找不到继续降的方式,即合法

(注意输入是$B$进制)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define M 7
5 #define maxB 6
6 #define mod 998244353
7 int n,m,x,B,base[N][M];
8 struct Complex{
9 int a[maxB];
10 Complex(){
11 memset(a,0,sizeof(a));
12 }
13 Complex(int x){
14 memset(a,0,sizeof(a));
15 a[0]=x;
16 }
17 Complex(int x,int y){
18 memset(a,0,sizeof(a));
19 a[0]=x,a[1]=y;
20 }
21 Complex operator + (const Complex &k)const{
22 Complex o;
23 for(int i=0;i<B;i++)o.a[i]=(a[i]+k.a[i])%mod;
24 return o;
25 }
26 Complex operator * (const Complex &k)const{
27 Complex o;
28 for(int i=0;i<B;i++)
29 for(int j=0;j<B;j++)o.a[(i+j)%B]=(o.a[(i+j)%B]+1LL*a[i]*k.a[j])%mod;
30 return o;
31 }
32 int get(){
33 if (B==5)return (a[0]-a[4]+mod)%mod;
34 return ((a[0]-a[3]+mod)%mod-(a[2]-a[5]+mod)%mod+mod)%mod;
35 }
36 }inv,A[maxB][maxB],AA[maxB][maxB],invA[maxB][maxB],a[N],b[maxB][N],f[N][maxB];
37 int read(){
38 int x=0;
39 char c=getchar();
40 while ((c<'0')||(c>'9'))c=getchar();
41 while ((c>='0')&&(c<='9')){
42 x=x*B+c-'0';
43 c=getchar();
44 }
45 return x;
46 }
47 Complex pow(Complex n,int m){
48 Complex s=n,ans=Complex(1);
49 while (m){
50 if (m&1)ans=ans*s;
51 s=s*s;
52 m>>=1;
53 }
54 return ans;
55 }
56 void DFT(Complex *a){
57 Complex aa[B];
58 for(int i=0,s=1;i<m;i++,s*=B)
59 for(int j=0;j<n;j++)
60 if (!base[j][i]){
61 for(int k=0;k<B;k++)aa[k]=Complex();
62 for(int k=0;k<B;k++)
63 for(int l=0;l<B;l++)aa[k]=aa[k]+a[j+l*s]*A[l][k];
64 for(int k=0;k<B;k++)a[j+k*s]=aa[k];
65 }
66 }
67 void IDFT(Complex *a){
68 Complex aa[B];
69 for(int i=0,s=1;i<m;i++,s*=B)
70 for(int j=0;j<n;j++)
71 if (!base[j][i]){
72 for(int k=0;k<B;k++)aa[k]=Complex();
73 for(int k=0;k<B;k++)
74 for(int l=0;l<B;l++)aa[k]=aa[k]+a[j+l*s]*invA[l][k];
75 for(int k=0;k<B;k++)a[j+k*s]=aa[k];
76 }
77 }
78 int main(){
79 scanf("%d%d%d",&n,&B,&m);
80 for(int i=0;i<n;i++){
81 x=read();
82 a[x]=a[x]+Complex(1);
83 }
84 n=1;
85 for(int i=0;i<m;i++)n*=B;
86 for(int i=0;i<n;i++){
87 base[i][0]=i%B;
88 for(int j=1;j<m;j++)base[i][j]=base[i/B][j-1];
89 }
90 inv=pow(Complex(B),mod-2);
91 for(int i=0;i<B;i++)
92 for(int j=0;j<B;j++){
93 A[i][j]=Complex(1);
94 AA[i][j]=pow(Complex(0,1),i*j);
95 invA[i][j]=pow(Complex(0,1),B*B-i*j)*inv;
96 }
97 for(int i=0;i<B;i++){
98 memcpy(b[i],a,sizeof(a));
99 DFT(b[i]);
100 for(int j=0;j<B;j++)
101 for(int k=0;k<B;k++)A[j][k]=A[j][k]*AA[j][k];
102 }
103 for(int i=0;i<n;i++)
104 for(int j=0;j<B;j++)
105 for(int k=0;k<B;k++)f[i][j]=f[i][j]+b[k][i]*invA[k][j];
106 for(int i=0;i<n;i++){
107 a[i]=Complex(1);
108 for(int j=0;j<B;j++)a[i]=a[i]*pow(pow(Complex(0,1),j)+Complex(1),f[i][j].get());
109 }
110 IDFT(a);
111 for(int i=0;i<n;i++)printf("%d\n",a[i].get());
112 }

[luogu5577]算力训练的更多相关文章

  1. 百度ERNIE 2.0强势发布!16项中英文任务表现超越BERT和XLNet

    2019年3月,百度正式发布NLP模型ERNIE,其在中文任务中全面超越BERT一度引发业界广泛关注和探讨. 今天,经过短短几个月时间,百度ERNIE再升级.发布持续学习的语义理解框架ERNIE 2. ...

  2. 星际争霸的虫王IA退役2年搞AI,自叹不如了

    ------------恢复内容开始------------ 金磊 发自 凹非寺 量子位|公众号 QbitA 这年头,直播讲AI,真算不上什么新鲜事.但要是连职业电竞选手,都开播主讲呢?没开玩笑,是真 ...

  3. YOLO 从数据集制作到训练

    1.图片数据集收集 共 16种 集装箱船 container ship 散货船 bulker 油船 tanker 游轮 / 客轮 / 邮轮 passenger liner 渔船 fishing boa ...

  4. ubuntu16.04安装tensorflow-gpu和cuda8.0加速训练

    转载请注明出处:http://www.cnblogs.com/buxizhizhoum/p/8086230.html 环境: 系统:ubuntu 16.04 cpu:i5 gpu:gt920m mem ...

  5. 华为云Volcano:让企业AI算力像火山一样爆发

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  6. 学习AI之NLP后对预训练语言模型——心得体会总结

    一.学习NLP背景介绍:      从2019年4月份开始跟着华为云ModelArts实战营同学们一起进行了6期关于图像深度学习的学习,初步了解了关于图像标注.图像分类.物体检测,图像都目标物体检测等 ...

  7. AI本质就是“暴力计算”?看华为云如何应对算力挑战

    随着AI人工智能技术的飞速发展,相关的AI应用场景已经拓宽至各行各业.你可能想象不到的是,现在大家手上的智能手机的运算能力,甚至比美国航空航天局1969年登月计划中最先进计算机还高出几百上千万倍乃至更 ...

  8. 转pytorch中训练深度神经网络模型的关键知识点

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_42279044/articl ...

  9. 【转载】BERT:用于语义理解的深度双向预训练转换器(Transformer)

    BERT:用于语义理解的深度双向预训练转换器(Transformer)   鉴于最近BERT在人工智能领域特别火,但相关中文资料却很少,因此将BERT论文理论部分(1-3节)翻译成中文以方便大家后续研 ...

随机推荐

  1. 【Docker】(9)---每天5分钟玩转 Docker 容器技术之镜像

    镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器.为什么我们要讨论镜像的内部结构? 如果只是使用镜像,当然不需要了解,直接通过 docker 命令下载和运行就可以了. 但如 ...

  2. 活动回顾|ShardingSphere X openGauss,将会产生怎样的化学反应?

    "ShardingSphere 作为 openGauss 生态的开源分布式数据库解决方案,将持续助力于 openGauss,满足千行百业广大客户分布式场景需求." 5月29日,由  ...

  3. 题解 CF736D Permutations

    link Description 现在,你有一个二分图,点数为 \(2n\). 已知这个二分图的完备匹配的个数是奇数. 现在你要知道,删除每条边后,完备匹配个数是奇数还是偶数. \(1\le n\le ...

  4. 「JOISC 2020 Day2」变态龙之色 题解

    题目传送门 注意 同性必定不同色 必有一个同色异性,且不相互不喜欢 Solution 我们发现,我们问题比较大的就是如何确定性别问题.我们可以一个一个加进去,在原来已经确定了的二分图上增加新的性别关系 ...

  5. cf1082D Maximum Diameter Graph(构造+模拟+细节)

    QWQ不得不说 \(cf\)的\(edu\ round\)出这种东西 有点太恶心了 题目大意:给你\(n\)个点,告诉你每个点的最大度数值(也就是说你的度数要小于等于这个),让你构造一个无向图,使其满 ...

  6. Java生成6位数验证码

    public static String getCode() { return String.valueOf((int) ((Math.random() * 9 + 1) * 100000));} 生 ...

  7. 手把手教你学Dapr - 1. .Net开发者的大时代

    Dapr全称 Distributed Application Runtime,分布式应用运行时 Dapr的口号 简化云原生应用开发,聚焦在应用的核心逻辑,让代码简单.可移植 Dapr的目标 最佳实践的 ...

  8. [Beta]the Agiles Scrum Meeting 3

    会议时间:2020.5.14 20:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 yjy 实现前端界面美化 tq 实现查看.删除测试点功能的前端修复功能中的bug wjx 升级系统实现 ...

  9. Java并发:重入锁 ReentrantLock(二)

    一.理解锁的实现原理 1. 用wait()去实现一个lock方法,wait()要和synchronized同步关键字一起去使用的,直接使用wait方法会直接报IllegalMonitorStateEx ...

  10. linux 内核源代码情景分析——i386 的页式内存管理机制

    可以看出,在页面目录中共有210 = 1024个目录项,每个目录项指向一个页面表,而在每个页面表中又共有1024个页面描述项. 由图看出来,从线性地址到物理地址的映射过程为: 1)从CR3取得页面目录 ...