HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)
传送门:HDU 5895 Mathematician QSC
这是一篇很好的题解,我想讲的他基本都讲了http://blog.csdn.net/queuelovestack/article/details/52577212
【分析】
一开始想简单了,对于a^x mod p这种形式的直接用欧拉定理的数论定理降幂了
结果可想而知,肯定错,因为题目并没有保证gcd(x,s+1)=1,而欧拉定理的数论定理是明确规定的
所以得另谋出路
那么网上提供了一种指数循环节降幂的方法
具体证明可以自行从网上找一找
有了这种降幂的方法之后,我们要分析一下如何求g(n)
由于f(0)=0,f(1)=1,f(n)=f(n−2)+2∗f(n−1)(n≥2)
可得,g(n)=f(n)*f(n+1)/2
这个是很好发现的
如果你发现不了的话,可以直接丢到OEIS里搜一下
然后,要求出g(n*y),就需要先求出f(n*y)和f(n*y+1)
这时,我们可以考虑用矩阵乘法
构造矩阵
套一下矩阵快速幂的模板就可以求出f(n*y)和f(n*y+1)
然后要求g(n)还有个除以2的操作,显然除法取模要用逆元
但考虑到2与模数不一定互质,无法用乘法逆元,所以要采用一点小技巧转化一下
这样我们就可以得到简化好的最终的指数部分
这样我们用快速幂就可以求x的幂次对(s+1)取模了
【时间复杂度&&优化】
O(1ogn)
/**************************************************************
Problem:hdu 5895 Mathematician QSC
User: youmi
Language: C++
Result: Accepted
Time:31MS
Memory:1584K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=*atan(1.0); using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
char c; int flag = ;
for (c = getchar(); !(c >= '' && c <= '' || c == '-'); c = getchar()); if (c == '-') flag = -, n = ; else n = c - '';
for (c = getchar(); c >= '' && c <= ''; c = getchar()) n = n * + c - ''; n *= flag;
}
ll Pow(ll base, ll n, ll mo)
{
ll res=;
while(n)
{
if(n&)
res=res*base%mo;
n>>=;
base=base*base%mo;
}
return res;
}
//*************************** ll n,y,x,s;
const ll mod=;
ll modp,modq;
const int maxn=; ll euler(ll nn)
{
ll res=nn,a=nn;
for(ll i=;i*i<=a;i++){
if(a%i==){
res=res/i*(i-);//先进行除法是为了防止中间数据的溢出
while(a%i==) a/=i;
}
}
if(a>) res=res/a*(a-);
return res;
}
struct matrix
{
ll mat[maxn][maxn];
matrix operator*(const matrix & rhs)const
{
matrix ans;
rep(i,,maxn-)
rep(j,,maxn-)
ans.mat[i][j]=;
rep(i,,maxn-)
rep(j,,maxn-)
rep(k,,maxn-)
ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*rhs.mat[k][j])%modp;
return ans;
}
matrix operator^(ll k)const
{
matrix rhs=*this;
matrix res;
rep(i,,maxn-)
rep(j,,maxn-)
res.mat[i][j]=(i==j);
while(k)
{
if(k&)
res=res*rhs;
rhs=rhs*rhs;
k>>=;
}
return res;
}
}xx; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int T_T;
scanf("%d",&T_T);
for(int kase=;kase<=T_T;kase++)
{
read(n),read(y),read(x),read(s);
modp=euler(s+)*;
modq=s+;
xx.mat[][]=,xx.mat[][]=,xx.mat[][]=,xx.mat[][]=;
matrix temp=xx^(n*y);
ll fn1=temp.mat[][];
ll fn=temp.mat[][];
ll gn=fn*fn1%modp/;
ll ans=Pow(x,gn,modq);
ptlld(ans);
}
return ;
}
HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)的更多相关文章
- hdu 5895 Mathematician QSC 指数循环节+矩阵快速幂
Mathematician QSC Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU 5895 Mathematician QSC
矩阵快速幂,欧拉定理. $g(n)$递推式:$g(n)=5g(n-1)+5g(n-2)-g(n-3)$,可以构造矩阵快速求递$n$项,指数很大,可以利用欧拉定理降幂. #pragma comment( ...
- HDU 3923 Invoker(polya定理+乘法逆元(扩展欧几里德+费马小定理))
Invoker Time Limit : 2000/1000ms (Java/Other) Memory Limit : 122768/62768K (Java/Other) Total Subm ...
- HDU 2814 斐波那契循环节 欧拉降幂
一看就是欧拉降幂,问题是怎么求$fib(a^b)$,C给的那么小显然还是要找循环节.数据范围出的很那啥..unsigned long long注意用防爆的乘法 /** @Date : 2017-09- ...
- hdu 3037 费马小定理+逆元除法取模+Lucas定理
组合数学推推推最后,推得要求C(n+m,m)%p 其中n,m小于10^9,p小于1^5 用Lucas定理求(Lucas定理求nm较大时的组合数) 因为p数据较小可以直接阶乘打表求逆元 求逆元时,由费马 ...
- [hdu5392 Infoplane in Tina Town]置换的最小循环长度,最小公倍数取模,输入挂
题意:给一个置换,求最小循环长度对p取模的结果 思路:一个置换可以写成若干循环的乘积,最小循环长度为每个循环长度的最小公倍数.求最小公倍数对p取模的结果可以对每个数因式分解,将最小公倍数表示成质数幂的 ...
- HDU 2604 Queuing (矩阵乘法)
Queuing Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- HDU 3746 Cyclic Nacklace (KMP求循环节问题)
<题目链接> 题目大意: 给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数. [>>>kmp next函数 kmp的周期问题] #include &l ...
- HDU 5607 graph(矩阵乘法)
题意 在一个 \(n\) 个节点 \(m\) 条边的有向图上随机游走,有 \(Q\) 个询问,每次给定一个起点 \(u\) 和步数 \(K\) ,每次回答最后停在每个节点的概率. \(1 \leq n ...
随机推荐
- Harp – 内置常用预处理器的静态 Web 服务器
Harp 是一个基于 Node.js 平台的静态 Web 服务器,内置流行的预处理器,支持把 Jade, Markdown, EJS, Less, Stylus, Sass, and CoffeeSc ...
- 高性能javascript学习笔记系列(4) -算法和流程控制
参考高性能javascript for in 循环 使用它可以遍历对象的属性名,但是每次的操作都会搜索实例或者原型的属性 导致使用for in 进行遍历会产生更多的开销 书中提到不要使用for in ...
- #8.11.16总结#CSS常用样式总结(二)
border 边框 简写:border:1px solid #000; 等效于:border-width:1px;border-style:solid;border-color:#000; 顺序:b ...
- Sublime Text 3汉化中文版
Sublime Text 3汉化中文版是Sublime Text2的升级版.Sublime Text 是一款流行的文本编辑器软件,有点类似于TextMate,跨平台,可运行在Linux,Windows ...
- 由Vue引发的getter和setter思考
公司的新项目决定使用Vue.js来做,当我打印出Vue实例下的data对象里的属性时,发现了一个有趣的事情: 它的每个属性都有两个相对应的get和set方法,我觉的这是多此一举的,于是去网上查了查Vu ...
- html5学习笔记:canvas
1.什么是canvas? 可以绘制图形的标签.一般用javascript来绘制. 2.创建一个画布 <!DOCTYPE html> <html> <head> &l ...
- SharePoint回环检查(Loopback Check)相关问题
Loopback Check(回环检查)本来不是一个SharePoint问题,是Windows Server为了增强自身安全性在Server 2003 SP1后引入的一个功能, 在近几个月中导致了一系 ...
- Autodesk Cloud Accelerator Program 开始报名
如果你没有注意到这个消息,那你就会错过一个前往旧金山和硅谷工程师一起工作数周的机会. 摘要一下: 时间: 1月10前提交你的提案,3月飞往旧金山 地点: 旧金山. 包住宿哦~ 不过,既然要去美国,既然 ...
- Xcode插件
Xcode插件-2016-03-10Xcode插件管理神器 —— Alcatraz 说明 Alcatraz是一个管理Xcode开源包的,你可以用它查找安装你想要的插件,模板以及配色方案,而你无需手动克 ...
- C++语言-06-文件操作
C语言文件操作 C++语言是C语言的超集,是在C语言的基础上增加了面向对象的特性而创造出来的,最初被命名为带类的C.所以C++语言中包含了C语言的思想,如:C++语言中文件操作的原理与步骤与C语言基本 ...