HDU6395(分段+矩阵快速幂)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=6395
给你一个式子,给出你A,B,C,D,P,n,让你求出第n项的式子Fn。(其中ABCDPn均在1e9的范围内)
分析: 如果Fn=C*F(n-2) + D*F(n-1) + num ; 我们就可以直接构造出这个斐波那契的矩阵快速幂 :写出相似的矩阵
1.f(n)=a*f(n-1)+b*f(n-2)+c;(a,b,c是常数)
但是这里的P/n 是变化的 , 我们无法转化出来 , 但是这里 P/n 是向下取整 也 就是说会有一段一段的区间里面的 p/i 是相等的 ; 所以我们现在找到这些一段一段然后用矩阵快速幂
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
const int mod=1e9+;
typedef long long ll;
struct Marix{
ll mo[][];
Marix(){
memset(mo,,sizeof(mo));
}
};
Marix mul(Marix a,Marix b){
Marix c;
for(int i=;i<;i++){
for(int j=;j<;j++){
for(int k=;k<;k++){
c.mo[i][j]=(c.mo[i][j]+a.mo[i][k]*b.mo[k][j])%mod;
}
}
}
return c;
}
Marix powmod(Marix a,ll n){//矩阵快速幂模板
Marix tmp;
for(int i=;i<;i++){
tmp.mo[i][i]=;
}
while(n){
if(n&) tmp=mul(tmp,a);
n>>=;
a=mul(a,a);
}
return tmp;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
ll a,b,c,d,p,n;
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&n);
if(n==){
printf("%lld\n",a);
continue;
}
if(n==){
printf("%lld\n",b);
continue;
}
Marix m;
m.mo[][]=d,m.mo[][]=c,m.mo[][]=,m.mo[][]=;
bool vis=;
for(ll i=;i<=n;){
if(p/i==){//倘若当前项大于p了,则直接用矩阵快速幂求解剩下的项
Marix tmp;
tmp=m;
tmp=powmod(tmp,n-i+);
ll res=(tmp.mo[][]*b+tmp.mo[][]*a+tmp.mo[][])%mod;
printf("%lld\n",res);
vis=;
break;
}//否则,不断的分段求解矩阵的值,并将矩阵的值进行修改
ll j=min(n,p/(p/i));
Marix tmp;
tmp=m;
tmp.mo[][]=p/i;
tmp=powmod(tmp,j-i+);
ll A=(tmp.mo[][]*b+tmp.mo[][]*a+tmp.mo[][])%mod;
ll B=(tmp.mo[][]*b+tmp.mo[][]*a+tmp.mo[][])%mod;
a=A,b=B;
i=j+;
}
if(!vis) printf("%lld\n",b);
}
return ;
}
新感受!
做的时候大概的想法是想到的了 , 但是无法解决F1=A, F2=B , 的情况 , 之后看的别人的代码才大悟出来 ;
只要求出最后的答案后,在成系数
fn=mo[0][0]*(f2) + mo[0][1]*(f1) 就好拉
例如
ll ans=(tmp.mo[0][0]*b+tmp.mo[0][1]*a+tmp.mo[0][2])%mod;
参考代码
/*
* Author: windystreet
* Date : 2018-08-14 09:46:10
* Motto : Think twice, code once.
*/
#include<bits/stdc++.h> using namespace std; #define X first
#define Y second
#define eps 1e-5
#define gcd __gcd
#define pb push_back
#define PI acos(-1.0)
#define lowbit(x) (x)&(-x)
#define bug printf("!!!!!\n");
#define mem(x,y) memset(x,y,sizeof(x)) typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef unsigned long long uLL; const int maxn = 1e5+;
const int INF = <<;
const int mod = 1e9+; struct Matrix
{
int n,m;
LL ma[][];
Matrix (int x,int y):n(x),m(y){clear();}
void set(int n_,int m_){n = n_,m = m_;}
LL *operator[](int x){return ma[x];}
Matrix operator*(Matrix x){
Matrix res(n,x.m);
for(int i=;i<=n;i++)
for(int j=;j<=x.m;j++)
for(int k=;k<=m;k++)
(res[i][j]+=ma[i][k]*x[k][j]%mod+mod)%=mod;
return res;
}
Matrix operator ^(int y){
Matrix x(n,m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
x[i][j]=ma[i][j];
Matrix res(x.n,x.n);
for(int i=;i<=x.n;i++)
res[i][i]=;
for(;y;y>>=,x=x*x)
if(y&)res=res*x;
return res;
}
void print(){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
printf("%lld%c",ma[i][j]," \n"[j==m]);
}
void clear(){mem(ma,);}
};
int a ,b,c,d ,p,n;
pii f(int x,int y){
if(!x)return make_pair(y,n);
int l = max(y,(p+x+)/(x+)),r = min(n,p/x);
return make_pair(l,r);
} void solve(){
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&p,&n);
if(n==)printf("%d\n",a);
if(n==)printf("%d\n",b);
else{
Matrix x(,),y(,);
x[][] = b,x[][]=a,x[][]=;
for(int i=;i<=n;){
pii seg = f(p/i,i);
y[][]=d,y[][] = ,y[][] = ;
y[][]=c,y[][] = ,y[][] = ;
y[][]=p/i,y[][]=,y[][] = ;
x = x*(y^(seg.Y - seg.X + ));
i = seg.Y+;
}
printf("%lld\n",x[][] );
} return;
} int main()
{
// freopen("F:\\in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// ios::sync_with_stdio(false);
int t = ;
scanf("%d",&t);
while(t--){
// printf("Case %d: ",cas++);
solve();
}
return ;
}
HDU6395(分段+矩阵快速幂)的更多相关文章
- BZOJ 2326 数学作业(分段矩阵快速幂)
实际上,对于位数相同的连续段,可以用矩阵快速幂求出最后的ans,那么题目中一共只有18个连续段. 分段矩阵快速幂即可. #include<cstdio> #include<iostr ...
- HDU 6395 分段矩阵快速幂 HDU 6386 建虚点+dij
http://acm.hdu.edu.cn/showproblem.php?pid=6395 Sequence Time Limit: 4000/2000 MS (Java/Others) Me ...
- HDU 6395 Sequence(分段矩阵快速幂)题解
题意: 已知\(A,B,C,D,P,n\)以及 \[\left\{ \begin{aligned} & F_1 = A \\ & F_2 = B\\ & F_n = C*F_{ ...
- hdu6395 (矩阵快速幂+分块)
Online Judge Online Exercise Online Teaching Online Contests Exercise Author F.A.Q Hand In Hand Onli ...
- HDU6395 Sequence(矩阵快速幂+数论分块)
题意: F(1)=A,F(2)=B,F(n)=C*F(n-2)+D*F(n-1)+P/n 给定ABCDPn,求F(n) mod 1e9+7 思路: P/n在一段n里是不变的,可以数论分块,再在每一段里 ...
- 数学--数论--HDU - 6395 Let us define a sequence as below 分段矩阵快速幂
Your job is simple, for each task, you should output Fn module 109+7. Input The first line has only ...
- hdu6395 Sequence(分段矩阵快速幂)
Sequence 题目传送门 解题思路 可以比较容易的推出矩阵方程,但是由于p/i向下取整的值在变,所以要根据p/i的变化将矩阵分段快速幂.p/i一共有sqrt(p)种结果,所以最多可以分为sqrt( ...
- hdu6395 /// 分块矩阵快速幂
题目大意: F(1)=A, F(2)=B, F(i)=C*F(i-2)+D*F(i-1)+p/i(向下取整) 给定A B C D p n 求F(n) 构造 矩阵A * 矩阵B = ...
- [hdu-6395]Sequence 分块+矩阵快速幂
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6395 因为题目数据范围太大,又存在递推关系,用矩阵快速幂来加快递推. 每一项递推时 加的下取整的数随 ...
随机推荐
- 框架面试题:谈谈我对Spring IOC与DI的理解
IOC是一种叫做“控制反转”的设计思想. 1.较浅的层次——从名字上解析 “控制”就是指对 对象的创建.维护.销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个 ...
- Apr编程
一.简介 http://www.xuebuyuan.com/2195578.html 二.教程 http://dev.ariel-networks.com/apr/
- Luogu 2597 [ZJOI2012]灾难
BZOJ 2815. 解法还是挺巧妙的. 放上写得很详细很好懂的题解链接 戳这里. 一个物种$x$如果要灭绝,那么沿着它的入边反向走走走,一定可以走到一个点$y$,如果这个点$y$的物种灭绝了,那么 ...
- jqgrid控件列分组
<%-- builed by manage.aspx.cmt [ver:2014.48.11] at 2014/10/11 16:48:33 --%> <%@ Page Langua ...
- 第一章Python简介
1.Python shell(Python命令解释器) 如下所示 2.Python的交互模式 如下 3.代码编辑器窗口 在上面的那些指令称为源代码. 4.在python中,缩进是有语法意义的. 在某行 ...
- URL 与 URI
http://localhost:8080/TEST_Servlet/ClientRequest/test?name=wr getRequestURL:http://localhost:8080/TE ...
- 详解servlet的url-pattern匹配规则.RP
首先需要明确几容易混淆的规则: servlet容器中的匹配规则既不是简单的通配,也不是正则表达式,而是特定的规则.所以不要用通配符或者正则表达式的匹配规则来看待servlet的url-pattern. ...
- Android onKeyDown、onKeyUp、dispatchKeyEvent的区别
1. onKeyDown.onKeyUp.dispatchKeyEvent的区别和使用场景 区别: 1.1 onKeyDown.onKeyUp是按键事件的回调接口(冒泡式调用),dispatchKey ...
- 编写高质量代码改善C#程序的157个建议——建议27:在查询中使用Lambda表达式
建议27:在查询中使用Lambda表达式 LINQ实际上是基于扩展方法和Lambda表达式的.任何LINQ查询都能通过扩展方法的方式来代替. var personWithCompanyList = f ...
- 【Head First Java 读书笔记】(四)对象的行为
状态影响行为,行为影响状态 对象有状态和行为 类所描述的是对象知道什么和执行什么. 同一类型的每个对象能够有不同的方法行为吗? 任一类的每个实例都带有相同的方法,但是方法可以根据实例变量的值来表现不同 ...