题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3240

  这道题其实有普通快速幂+费马小定理的解法……然而我太弱了,一开始只想到了矩阵乘法的方法。

  首先定义两个矩阵:

  $ A_{1} = \begin{bmatrix} a & b \\ 0 & 1 \end{bmatrix} $
  $ A_{2} = \begin{bmatrix} c & d \\ 0 & 1 \end{bmatrix} $

  于是我们就可以得到这样的式子:

  $ \begin{aligned}  \begin{bmatrix} f_{n,m} \\ 1 \end{bmatrix} & = A_{1} \begin{bmatrix} f_{n,m-1} \\ 1 \end{bmatrix} \\ & = A_{1}^{m-1} \begin{bmatrix} f_{n,1} \\ 1 \end{bmatrix} \\ & = A_{1}^{m-1} A_{2}\begin{bmatrix} f_{n-1,m} \\ 1 \end{bmatrix} \\ & = ( A_{1}^{m-1}  A_{2} )^{n-1} \begin{bmatrix} f_{1,m} \\ 1 \end{bmatrix} \\ & = ( A_{1}^{m-1} A_{2} )^{n-1}  A_{1}^{m-1} \begin{bmatrix} f_{1,1} \\ 1 \end{bmatrix}  \end{aligned} $

  然后用一发10进制矩阵快速幂能解决这道题了。

  然而……这种做法跑的极慢。在洛谷上还能以近2000msAC,放到bzoj的6元cpu上跑就有些力不从心了,,所以得卡常数。

  经过了十几次提交,使用了奥义·卡常数:10^18进制进制快速幂+循环展开+register后终于卡进了时限。。。

  代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define base 1000000000000000000ll
#define eps 1e-18
inline ll read()
{ll tmp=0; char c=getchar(),f=1;for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1;for(;'0'<=c&&c<='9';c=getchar())tmp=tmp*10+c-'0';return tmp*f;
}
using namespace std;
struct mat{ll num[2][2];
}mat1,mat2;
struct hp{ll num[1000010];int len;
}n,m;
char s[1000010],t[1000010];
ll a,b,c,d;
mat times(mat a,mat b)
{mat c;c.num[0][0]=(a.num[0][0]*b.num[0][0]+a.num[0][1]*b.num[1][0])%mod;c.num[0][1]=(a.num[0][0]*b.num[0][1]+a.num[0][1]*b.num[1][1])%mod;c.num[1][0]=(a.num[1][0]*b.num[0][0]+a.num[1][1]*b.num[1][0])%mod;c.num[1][1]=(a.num[1][0]*b.num[0][1]+a.num[1][1]*b.num[1][1])%mod;return c;
}
mat power_num(mat a,ll b)
{mat ans; ans.num[0][0]=ans.num[1][1]=1; ans.num[0][1]=ans.num[1][0]=0;while(b){if(b&1)ans=times(ans,a);a=times(a,a); b>>=1;}return ans;
}
mat power(mat a,hp b)
{mat ans; ans.num[0][0]=ans.num[1][1]=1; ans.num[0][1]=ans.num[1][0]=0;for(register int i=1;i<=b.len;i++){ans=times(ans,power_num(a,b.num[i]));a=power_num(a,base);}return ans;
}
int main()
{register int i;scanf("%s",s); scanf("%s",t); a=read(); b=read(); c=read(); d=read();mat1.num[0][0]=a; mat1.num[0][1]=b; mat1.num[1][0]=0; mat1.num[1][1]=1;mat2.num[0][0]=c; mat2.num[0][1]=d; mat2.num[1][0]=0; mat2.num[1][1]=1;int len1=strlen(s),len2=strlen(t);for(i=1;i*18<=len1;i++){n.num[i]=0;for(register short j=18;j;j--)n.num[i]=n.num[i]*10+s[len1-(i-1)*18-j]-'0';}n.len=len1/18;if(len1%18){n.num[++n.len]=0;for(register short j=0;j<len1%18;j++)n.num[n.len]=n.num[n.len]*10+s[j]-'0';}for(i=1;i*18<=len2;i++){m.num[i]=0;for(register short j=18;j;j--)m.num[i]=m.num[i]*10+t[len2-(i-1)*18-j]-'0';}m.len=len2/18;if(len1%18){m.num[++m.len]=0;for(register short j=0;j<len2%18;j++)m.num[m.len]=m.num[m.len]*10+t[j]-'0';}n.num[1]-=1;for(i=1;i<=n.len;i++)if(n.num[i]<0)n.num[i]+=base,n.num[i+1]-=1;if(n.num[n.len]==0&&n.len>1)--n.len;m.num[1]-=1;for(i=1;i<=m.len;i++)if(m.num[i]<0)m.num[i]+=base,m.num[i+1]-=1;if(m.num[m.len]==0&&m.len>1)--m.len;mat hang=power(mat1,m);mat ans=times(power(times(hang,mat2),n),hang);printf("%lld\n",(ans.num[0][0]+ans.num[0][1])%mod);
}

bzoj3240


解法2:

  我们可以发现把$f_{1,i}=af_{i-1}+b$不断地展开后就能得到$f_{1,i}=a^i f_{1,1}+b\sum_{k=0}^{i-1}a^{k}$,即$f_{2,1}=a^{i}cf_{1,1}+bc\sum_{k=0}^{m-1}a^{k}+d$,于是我们可以用等比数列求和公式化简这个式子,又因为1e9+7是质数,所以可以由费马小定理将指数对1e9+6取模(不过需特判$a=1$的情况)。

  然后我们可以发现这个式子也是$f_{i,1}=af_{i-1,1}+b$的形式(其中$ a,b $是常数),于是用上面的方法求出$f_{n+1,1}$,然后$f_{n,m}$就好求了。

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-18
inline ll read()
{ll tmp=0; char c=getchar(),f=1;for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1;for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0';return tmp*f;
}
using namespace std;
char s[1000010],t[1000010];
ll a,b,c,d,n,m;
ll power(ll a,ll b)
{ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod; b>>=1;}return ans;
}
int main()
{int i;scanf("%s",s); scanf("%s",t); a=read(); b=read(); c=read(); d=read();int len1=strlen(s),len2=strlen(t);m=0;for(i=0;i<len2;i++)m=(m*10+t[i]-'0')%(a>1?mod-1:mod);ll p=power(a,m-1)*c%mod,q=((a>1?(power(a,m-1)+mod-1)*power(a+mod-1,mod-2)%mod:m-1)*b%mod*c%mod+d)%mod;for(i=0;i<len1;i++)n=(n*10+s[i]-'0')%(p>1?mod-1:mod);ll ans=(power(p,n)+(p>1?(power(p,n)+mod-1)*power(p+mod-1,mod-2)%mod:n)*q)%mod;printf("%lld\n",(ans+mod-d)*power(c,mod-2)%mod);
}

bzoj3240

转载于:https://www.cnblogs.com/quzhizhou/p/8521667.html

【bzoj3240 洛谷P1397】矩阵游戏[NOI2013](矩阵乘法+卡常)相关推荐

  1. 洛谷 P2197 nim游戏

    洛谷 P2197 nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取 ...

  2. 洛谷 P1558 色板游戏

    传送门:洛谷 P1558 色板游戏 算法分析:观察到数据范围:\(1\leq T\leq 30\) ,考虑使用二进制来进行状态压缩 将颜色\(x\)表示为 \(1<<(x-1)\) 即 \ ...

  3. 洛谷 P3041 视频游戏的连击Video Game Combos(AC自动机+拓扑排序+数位DP)

    洛谷 P3041 视频游戏的连击Video Game Combos 难度一般,不过这个数位DP其实应该叫做记忆化搜索 题意:玩游戏时可以通过按键组合打出combo技能:然后是已知N个combo的按键方 ...

  4. 洛谷P3758/BZOJ4887 [TJOI2017] 可乐 [矩阵快速幂]

    洛谷传送门,BZOJ传送门 可乐 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 299  Solved: 207 Description 加里敦星球的 ...

  5. 【洛谷1527】 [国家集训队]矩阵乘法(整体二分)

    传送门 洛谷 Solution 考虑看到什么k小就整体二分套上去试一下. 矩形k小整体二分+二维树状数组就好了. 代码实现 // luogu-judger-enable-o2 /*mail: mlea ...

  6. 动态规划——洛谷_P1057传球游戏

    题目: 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏.游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球, ...

  7. 洛谷——P1000 超级玛丽游戏

    P1000 超级玛丽游戏 题目背景 本题是洛谷的试机题目,可以帮助了解洛谷的使用. 建议完成本题目后继续尝试P1001.P1008. 另外强烈推荐新用户必读贴 题目描述 超级玛丽是一个非常经典的游戏. ...

  8. 洛谷P1000 超级玛丽游戏C++题解

    首先我们看这道题的题目"超级玛丽游戏",第一道题就让我们写个游戏出来.结果点进去一看,顿时觉得这道题是在开玩笑,本题是洛谷的试机题目,可以帮助了解洛谷的使用. 建议完成本题目后继续 ...

  9. 洛谷 P4815 狼人游戏 题解

    洛谷 P4815 [CCO2014] 狼人游戏 首先题目中有 3 3 3 个限制: 没有机器人又被指控又被保护: 没有机器人被指控或保护一次以上: 如果有一个编号为 A A A 机器人指控或保护编号为 ...

最新文章

  1. 【Qt】Qt动态库和静态库的创建和使用
  2. TOJ-1036.Rails STL-栈
  3. maven构建本地jar包到本地仓库
  4. Java 的 IO 流
  5. Excel 数据有效性,怎么提示指定的命名区域不存在?
  6. BitNami Redmine Stack
  7. 生成某一文件夹内文件清单(批量处理)
  8. 极度推荐的文章和网站
  9. 华为正式发布鸿蒙智慧屏,5499 元、21999 元,2021 款华为智慧屏 V55/V85 明日 0 点正式开售:搭载鸿蒙系统...
  10. 为什么大部分的婚姻都是凑合?数据告诉你真相
  11. eclipse更改android版本,在Android Studio和Android Eclipse 更改现有项目里的SDK版本
  12. django发送邮件结合itsdangerous+celery+redis
  13. 博图中fb与多重背景数据块_STEP7中如何生成和更新多重背景?
  14. QQ和MSN 在线代码
  15. 【Kettle Spoon】数据迁移Spoon的使用
  16. APS自动排产 — 排产结果拉动物料需求计划
  17. SUNDIALS中的RTOL和ATOL
  18. c语言电话本程序代码,C语言程序设计之电话簿
  19. 诺基亚7原生android,诺基亚7快速上手体验:蔡司镜头回归,原生Android味
  20. SQL的主键和外键的设置语法

热门文章

  1. 【Qt学习笔记】包含头文件确报错 does not name a type
  2. java 打开word(docx)替换内容,并插入图片(盖章)
  3. 短信平台市场蒸蒸日上的根本原因
  4. android 程序运行不了,Android程序运行时,真机不能用
  5. Android 7.0修改PMS逻辑添加权限白名单
  6. 通过手机使用广域网访问局域网的服务器
  7. 内功图说--十二段锦
  8. 闪迪u盘不能识别好办法_SanDisk U盘无法识别解决
  9. linux 自动降频,Linux资格认证:Ubuntu下对CPU进行降频
  10. day08---(05)课程大纲-章节和小节列表功能(接口)