【题目描述】

有一个星球要创造新的单词,单词有一些条件:

  1. 字母集有\(p\)个元音和\(q\)个辅音,单词由字母构成
  2. 每个单词最多有\(n\)个元音和\(n\)个辅音(同一元音或辅音可重复使用)
  3. 每个单词中元音总是出现在所有辅音之前,可以没有元音或没有辅音
  4. 每个单词至少有一个字母
  5. 可以在字母上标记重音。元音中最多标记一个,辅音中也最多标记一个,一个单词中最多标记两个字母为重音
  6. 如果两个单词字母、字母顺序或者重音不同就认为这两个单词不同。

他们想要知道一共能创造多少不同的单词,由于答案可能很大,所以只要输出答案mod M后的值。

【输入格式】

输入文件word.in包含4个正整数\(p,q,n,M\)

【输出格式】

输出文件word.out包含一个非负整数表示能创造出的新单词数 mod M 后的值。

【样例输入1】

1 1 1 9

【样例输出1】

8

【样例输入2】

2 3 2 1000

【样例输出2】

577

【样例输入3】

1 1 1000000000 1000000000

【样例输出3】

0

【数据规模】

对于 \(30\%\)的数据,\(p, q, n\le 7\)

对于\(60\%\)的数据,\(n \le 100000\)

对于\(100\%\)的数据,$ p, q, n, M ≤ 10^9$

题解

个人认为这题的题目描述可能会造成一点小小的误解。那就是“所有”的元音都应该放在辅音之前,即元辅音可以分开来看

那我们就只看元音吧。

于是我们就可以很自然地推出\(ans=\sum_{i=1}^n(i+1)p^i\)。由于有一个叫重音的东西,所以系数是\(i+1\)。直接算会T(70分),于是我们就想到了矩阵快速幂(orz严公分块、倍增)。

首先我们当然想到是推\(2\times 2\)的,于是写出初始矩阵\(\begin{bmatrix}0 & 2p \end{bmatrix}\),要转移到\(\begin{bmatrix}2p & 3p^2+2p\end{bmatrix}\)。发现矩阵的系数有变化,无法转移。于是我们就需要添加一格来辅助转移。观察两矩阵的系数变化,我们就不难推出辅助的那个应该填什么:\(\begin{bmatrix}0&p&2p\end{bmatrix}\to \begin{bmatrix}2p&p^2&3p^2+2p\end{bmatrix}\)。于是得出中间矩阵是\(\begin{bmatrix}1&0&0\\0&p&p\\1&0&p\end{bmatrix}\)话说个人这题的矩阵的推法挺精妙的,建议仔细回味一下)。

然后就用同样的方法算辅音即可。

代码

#include <cstring>
#include <cmath>
#include <fstream> using namespace std; typedef long long LL; ifstream fin("word.in");
ofstream fout("word.out"); LL chen[4][4], q, p, n, mod, jg[2][4], tt[4][4]; inline void pow(int aa)
{
while(aa)
{
if(aa & 1)
{
for(int j = 1; j <= 3; ++j)
{
tt[1][j] = 0;
for(int k = 1; k <= 3; ++k)
tt[1][j] = (tt[1][j] + jg[1][k] * chen[k][j] % mod) %mod;
}
memcpy(jg, tt, sizeof(jg));
}
aa >>= 1;
for(int i = 1; i <= 3; ++i)
for(int j = 1; j <= 3; ++j)
{
tt[i][j] = 0;
for(int k = 1; k <= 3; ++k)
tt[i][j] = (tt[i][j]+chen[i][k]*chen[k][j]%mod)%mod;
}
memcpy(chen, tt, sizeof(chen));
}
} int main()
{
fin >> q >> p >> n >> mod;
jg[1][1] = (q<<1) % mod;
jg[1][2] = q % mod;
chen[1][1] = chen[2][1] = chen[2][2] = q % mod;
chen[1][3] = chen[3][3] = 1;
pow(n);
LL sumy = jg[1][3];
memset(jg, 0, sizeof(jg));
memset(chen, 0, sizeof(chen));
jg[1][1] = (p<<1) % mod;
jg[1][2] = p%mod;
chen[1][1] = chen[2][1] = chen[2][2] = p % mod;
chen[1][3] = chen[3][3] = 1;
pow(n);
LL sumf = jg[1][3];
LL ans = (sumy*sumf%mod + sumy + sumf) % mod;
fout << ans;
return 0;
}

最新文章

  1. git与github使用
  2. error the @annotation pointcut expression is only supported at Java 5 compliance
  3. 10天学会phpWeChat——第三天:从数据库读取数据到视图
  4. iOS-Gdata XML解析配置和简单使用
  5. 15. Linked List Cycle &amp;&amp; Linked List Cycle II
  6. 在脚本中操作plist文件
  7. 如何在Azure上动态配置IP地址
  8. 两个winform窗体同步
  9. C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]
  10. Visual Studio 2013 Use HTTPS (SSL) On Web Application Projects
  11. 堆排序—Java
  12. 浅谈 URI 及其转义
  13. win7 Anaconda 安装 scrapy模块
  14. 勤拂拭软件Android开发之旅(1) 之 Android 开发环境搭建
  15. comtypes加word 2013批量将pdf转换为doc
  16. Python爬虫入门教程 60-100 python识别验证码,阿里、腾讯、百度、聚合数据等大公司都这么干
  17. 2019-01-23 JavaScript实现ZLOGO: 性能改进
  18. LOJ#6118 鬼牌
  19. git and github问题集锦
  20. Easy Ui 的reload 问题

热门文章

  1. 4 实战CPU上下文
  2. PHP重命名文件夹下的文件后缀名
  3. CentOS6.5 更新gcc-7.3.0
  4. Java学习:JDBC各类详解
  5. SUSE12SP3-Samba配置
  6. AppTheme属性设置集合
  7. rsync+inotify实现多台服务器之间数据实时同步
  8. 关于Mysql datetime类型存储范围测试
  9. js浏览器对象模型【BOM】(十三)
  10. Beego 学习笔记一:环境的配置