2017 多校训练第二场 HDU 6050 Funny Function

本文介绍了一种通过数学规律推导公式的方法,并利用矩阵快速幂进行高效计算。该方法适用于解决特定类型的数学问题,特别是在处理大数运算时能够显著提高效率。

找规律推公式,数学做法

#include <bits/stdc++.h>
using namespace std;
// #define test TEST 
const int maxn=10005;
const int mod=1e9+7;

typedef long long ll;
ll x,y;

ll Quick_Mod(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1LL) ans=((ans%mod)*(a%mod))%mod;
		a=(a%mod)*(a%mod)%mod;
		b>>=1;
	}
	return ans;
}

ll inv(ll a){
	return Quick_Mod(a,mod-2);
}

int main(int argc, char const *argv[])
{
	#ifdef test 
	freopen("test.txt","r",stdin);
	#endif 
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%lld %lld",&x,&y);
		ll ans=1;
		if(x&1LL){
			ans=(Quick_Mod(Quick_Mod(2,x)-1,y-1)*2%mod+1)*inv(3)%mod;
		}
		else{
			ans=(Quick_Mod(Quick_Mod(2,x)-1,y-1)*2%mod)*inv(3)%mod;
		}
		printf("%lld\n",ans);
	}	
	return 0;
}

下面就是暴力了,用矩阵快速幂进行求解

#include <bits/stdc++.h>
using namespace std;
// #define test TEST 
const int maxn=10005;

typedef long long ll;
const ll mod=1e9+7;

ll x,y;

typedef struct Matrix{
	ll a[2][2];
	Matrix(ll a00,ll a01,ll a10,ll a11){
		a[0][0]=a00,a[0][1]=a01,a[1][0]=a10,a[1][1]=a11;
	}
	Matrix(){
		a[0][0]=a[1][1]=1,a[1][0]=a[0][1]=0;
	}
}M;

M operator * (const M &x,const M &y){
	M ans;
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			ans.a[i][j]=0;
			for(int k=0;k<2;k++){
				ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
			}
		}
	}
	return ans;
}

M qpow(M x,ll y){
	M ans;
	while(y){
		if(y&1) ans=ans*x;
		x=x*x;
		y>>=1;
	}
	return ans;
}

M operator - (const M &x,const M &y){
	M ans;
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			ans.a[i][j]=(x.a[i][j]-y.a[i][j]+mod)%mod;
		}
	}
	return ans;
}

// ll Quick_Mod(ll a,ll b){
// 	ll ans=1;
// 	while(b){
// 		if(b&1LL) ans=((ans%mod)*(a%mod))%mod;
// 		a=(a%mod)*(a%mod)%mod;
// 		b>>=1;
// 	}
// 	return ans;
// }

// ll inv(ll a){
// 	return Quick_Mod(a,mod-2);
// }

int main(int argc, char const *argv[])
{
	#ifdef test 
	freopen("test.txt","r",stdin);
	#endif 

	int T;
	scanf("%d",&T);
	M A(1,2,1,0),B1(1,0,0,1),B2(0,2,1,-1);
	while(T--){
		M ans;
		scanf("%lld %lld",&x,&y);
		if(x&1LL){
			ans=qpow(qpow(A,x)-B2,y-1);
		}
		else{
			ans=qpow(qpow(A,x)-B1,y-1);
		}
		printf("%lld\n",(ans.a[0][0]+mod)%mod);
	}	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值