【CF497E】Subsequences Return

题意:设$s_k(x)$表示x在k进制下各位数的和mod k的值。给出k,现有序列$s_k(1),s_k(2),...s_k(n)$。求这个序列有多少个本质不同的子序列。

$n\le 10^{18},k\le 30$

题解:状态非常巧妙(其实做过类似套路就知道了)。看到$n=10^{18}$就一定是让你矩乘了。我们希望构建出一个类似于自动机的东西,它能识别出一个序列的所有子序列,且点数最好是在$O(k)$级别的,怎么办呢?

假如我们真的构建出了一个自动机,那么对于他的一个状态x,现在新来了一个数a,如果a是x想要的,那么从x转移到其它状态,否则转移到自己。那我们不妨直接设x这个状态表示它下一个想要的数是x的方案数。如果匹配成功,则下一个想要的数可以是任意数,并使计数器+1,否则它想要的数还是自己。

接着考虑怎么矩乘,容易想到将x放到k进制下表示。用$A_{i,j}$表示$s_k(j\times k^i)..s_k((j+1)\times k^i-1)$这段数对应的转移矩阵。那么$A_{i,j}$其实就是$A_{i-1,j}A_{i-1,j+1}...A_{i-1,k-1}A_{i-1,0}...A_{i-1,j-1}$。用前缀和优化一下即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll P=1000000007;
int m,len;
ll n;
ll v[61]; struct M
{
ll v[31][31];
M () {memset(v,0,sizeof(v));}
ll * operator [] (const int &a) {return v[a];}
M operator * (const M &a) const
{
M b;
int i,j,k;
for(i=0;i<=m;i++) for(j=0;j<=m;j++) for(k=0;k<=m;k++) b.v[i][j]=(b.v[i][j]+v[i][k]*a.v[k][j])%P;
return b;
}
}T[60][30],S,s1[60][30],s2[60][30]; int main()
{
scanf("%lld%d",&n,&m);
v[0]=n;
while(v[len]) v[len+1]=v[len]/m,v[len]%=m,len++;
int i,j,a,b;
for(i=0;i<=m;i++) S[0][i]=1;
for(i=0;i<len;i++)
{
for(j=0;j<=m;j++) T[i][0][j][j]=1;
if(!i)
{
for(j=0;j<m;j++)
{
T[i][j][m][m]=1;
for(a=0;a<m;a++)
{
if(a!=j)
{
T[i][j][a][a]=1;
continue;
}
for(b=0;b<=m;b++) T[i][j][a][b]=1;
}
}
}
else
{
for(j=0;j<m;j++)
{
if(!j) T[i][j]=s2[i-1][0];
else T[i][j]=s2[i-1][j]*s1[i-1][j-1];
}
}
for(s1[i][0]=T[i][0],j=1;j<m;j++) s1[i][j]=s1[i][j-1]*T[i][j];
for(s2[i][m-1]=T[i][m-1],j=m-2;j>=0;j--) s2[i][j]=T[i][j]*s2[i][j+1];
}
for(i=len-1,j=0;i>=0;i--)
{
while(v[i]--) S=S*T[i][j],j=(j+1)%m;
}
printf("%lld",S[0][m]);
return 0;
}//1000000000000000000 2

【CF497E】Subsequences Return 矩阵乘法的更多相关文章

  1. *HDU2254 矩阵乘法

    奥运 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...

  2. *HDU 1757 矩阵乘法

    A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  3. CH Round #30 摆花[矩阵乘法]

    摆花 CH Round #30 - 清明欢乐赛 背景及描述 艺术馆门前将摆出许多花,一共有n个位置排成一排,每个位置可以摆花也可以不摆花.有些花如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看 ...

  4. POJ3070 Fibonacci[矩阵乘法]

    Fibonacci Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13677   Accepted: 9697 Descri ...

  5. bzoj 2738 矩阵乘法

    其实这题跟矩阵乘法没有任何卵关系,直接整体二分,用二维树状数组维护(刚刚学会>_<),复杂度好像有点爆炸(好像有十几亿不知道是不是算错了),但我们不能怂啊23333. #include&l ...

  6. 【BZOJ-2476】战场的数目 矩阵乘法 + 递推

    2476: 战场的数目 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 58  Solved: 38[Submit][Status][Discuss] D ...

  7. 【BZOJ-1898】Swamp 沼泽鳄鱼 矩阵乘法

    1898: [Zjoi2005]Swamp 沼泽鳄鱼 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1012  Solved: 566[Submit][S ...

  8. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  9. 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式

    矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b     *     A B   =   a*A+b*C  a*c+b*D c d     ...

随机推荐

  1. cout.setf()

    cout用来实现格式输出,类似于C语言中通过printf(). cout.setf()的作用是通过设置格式标志来控制输出形式,如,其中ios_base::fixed表示:用正常的记数方法显示浮点数(与 ...

  2. web的几种返回顶部

    回到顶部backtoTop 滚动回到顶部 jquery/js效果还不错!支持现代浏览器包括 ie6.position: absolute;和fixed.两种方法! 一,jQuery方法的backtoT ...

  3. Hibernate(8)_单向n对n

    1.n-n 的关联必须使用连接表 与1-n映射类似,必须为set集合元素添加 key 子元素,需要指定中间表 2.实体类 Category.java public class Category { p ...

  4. OpenXC : Any updates on plans for IOS?

    OpenXC : Any updates on plans for IOS? Hi Thomas, We're actively investigating this as we'd love to ...

  5. An entry point cannot be marked with the 'async' modifier

    I copied below code from this link.But when I am compiling this code I am getting an entry point can ...

  6. 修复恢复"可疑"的SQLServer数据库

    今天机房突然断电,DB连不上了,提示 无法打开数据库'MyDB'.恢复操作已将该数据库标记为 SUSPECT. 原因是断电导致DB文件损坏 通过SQL Server Management Studio ...

  7. 模拟位置 定位 钉钉打卡 运动轨迹 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  8. [Python设计模式] 第20章 挨个买票——迭代器模式

    github地址:https://github.com/cheesezh/python_design_patterns 迭代器模式 迭代器模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该 ...

  9. 需要看源码的java类

    1.数据结构相关的类,如String.ArrayList,LinkedList,HashMap和ConcurrentHashMap等等.2.线程并发相关的类,如Synchronized.Reentra ...

  10. Ubuntu 16.04常用快捷键

    注意:在Linux下Win键就是Super键 启动器 Win(长按) 打开启动器,显示快捷键 Win + Tab 通过启动器切换应用程序 Win + 1到9 与点击启动器上的图标效果一样 Win + ...