HDU 6395 Sequence 分段矩阵快速幂

题目连接

题意:就是求这个数列的前的第n项的值并mod1e9+7。

比赛的时候都知道是矩阵快速幂,但是就是不知道后面的向下取整怎么处理,后来看到题解说的是分段矩阵快速幂才恍然大悟。

思路:整个题就是这个后面的那个向下取整不好处理,我的思路是把后面那个看成一个反比例函数en=\frac{p}{n} 当n在某一定区间内时en是一定的,在前面n比较小的时候变化是比较大的,当n越来越大时en变化越来越小,所以我们把en相同的分为一段然后跑矩阵快速幂,其实一点都不难,就是因为不敢想不敢写。

代码:写的比较挫

#include<stdio.h>
#include<string.h>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const ll linf=8e18+9e17;
const int mod=1e9+7;
const double e=exp(1.0);
const double pi=acos(-1);
struct matrix{
	ll a[3][3];
};
matrix multipy(matrix a,matrix b)
{
	matrix  ans={0};
	for(int i=0;i<3;i++)
	for(int j=0;j<3;j++)
	for(int k=0;k<3;k++)
	ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
	return ans;
}
matrix quick_pow(matrix a,int n)
{
	matrix ans={0};
	for(int i=0;i<3;i++)ans.a[i][i]=1;
	while(n)
	{
		if(n&1)ans=multipy(ans,a);
		n/=2;
		a=multipy(a,a);
	}
	return ans;
}
ll getlimit(ll now,ll p)
{
	if(p/now!=p/(now+1))return now+1;
	else return p/((p/now)-(p%now==0))+(p%((p/now)-(p%now==0))!=0);//这个求一个分段的终点写的巨丑 
}
int main()
{
	int t;
	ll a,b,c,d,p,n,e;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&n);
		swap(a,b);
		if(n==1){printf("%lld\n",a);continue;}
		else if(n==2){printf("%lld\n",b);continue;}		
		matrix mat={d,c,1,1,0,0,0,0,1};
		ll st=3,en;
		while(st<=n)
		{
			if(st==p)en=st+1;
			else if(st>p)en=n+1 ;
			else {
					en=getlimit(st,p);//写的最搓的部分了 
			}
			matrix now=quick_pow(mat,min(n+1,en)-st);
			ll newa=(now.a[0][0]*a%mod+now.a[0][1]*b%mod+now.a[0][2]*(p/st)%mod)%mod;//F[n] 
			now=quick_pow(mat,min(n+1,en)-st-1);
			ll newb=(now.a[0][0]*a%mod+now.a[0][1]*b%mod+now.a[0][2]*(p/st)%mod)%mod;//F[n-1] 
			a=newa;
			if(min(n+1,en)>2)b=newb;
			st=en;
		}
		printf("%lld\n",a);
	}
	return 0;
}
/*
2
1 1 1 1 100 12
*/

猜你喜欢

转载自blog.csdn.net/swust5120166213/article/details/81664016
今日推荐