水题 矩阵快速幂

Description

函数 f:Z+Zf:Z+→Z。已知 f(1)f(2)f(1),f(2) 的值,且对于任意 x>1x>1,有 f(x+1)=f(x)+f(x1)+sin(πx2)f(x+1)=f(x)+f(x−1)+sin⁡(πx2)

求 f(n)f(n) 的值。

Input

多组数据。(数据组数 T100T≤100

每组数据包含 33 个不超过 109109 的正整数,分别代表 f(1)f(2)f(1),f(2) 和 nn 的值。

Output

 输出 f(n)mod(109+7)f(n)mod(109+7)。每组输出末尾有换行符。

Sample Input

1 2 3
1 2 5

Sample Output

3
7
题解:

 f(x+1)=f(x)+f(x1)+sin(πx2)f(x+1)=f(x)+f(x−1)+sin⁡(πx2) 看成是由斐波那契数列和sin(πx2)共同组成的函数

发现两部分都是含有fib数的函数,得到f(x+1)关于fib数的函数表达式,然后利用矩阵快速幂的方法求fib数


代码:

#include <cstdio>
#include <iostream>
#define int long long
using namespace std;
const int MOD = 1e9+7;
int d[4]={0,1,0,-1};
int f1,f2,n;
int fast_mod(int n)    // 求 (t^n)%MOD 
{
    int t[2][2] = {1, 1, 1, 0};
    int ans[2][2] = {1, 0, 0, 1};  // 初始化为单位矩阵
    int tmp[2][2];    //自始至终都作为矩阵乘法中的中间变量 
     
    while(n)
    {
        if(n & 1)  //实现 ans *= t; 其中要先把 ans赋值给 tmp,然后用 ans = tmp * t 
        {
            for(int i = 0; i < 2; ++i)
                for(int j = 0; j < 2; ++j)
                    tmp[i][j] = ans[i][j]; 
            ans[0][0] = ans[1][1] = ans[0][1] = ans[1][0] = 0;  // 注意这里要都赋值成 0 
            
            for(int i = 0; i < 2; ++i)    //  矩阵乘法 
            {
                for(int j = 0; j < 2; ++j)
                {
                    for(int k = 0; k < 2; ++k)
                        ans[i][j] = (ans[i][j] + tmp[i][k] * t[k][j]) % MOD;
                }
            }
        }
        
        //  下边要实现  t *= t 的操作,同样要先将t赋值给中间变量  tmp ,t清零,之后 t = tmp* tmp 
        for(int i = 0; i < 2; ++i)
            for(int j = 0; j < 2; ++j)
                tmp[i][j] = t[i][j];
        t[0][0] = t[1][1] = 0;
        t[0][1] = t[1][0] = 0;
        for(int i = 0; i < 2; ++i)
        {
            for(int j = 0; j < 2; ++j)
            {
                for(int k = 0; k < 2; ++k)
                    t[i][j] = (t[i][j] + tmp[i][k] * tmp[k][j]) % MOD;
            }
        }
        
        n >>= 1;
    }
    return ans[0][1];
}
int dfs(int x)
{
	if(x < 3) return 0;
	if(x == 3)
	{
		return d[2];
	}
	else if(x == 4)
	{
		return d[3]+d[2];
	}
	else
	{
		return dfs(x-1)+dfs(x-2) + d[(x-1)%4];
	}
}
main()
{
    
    while(~scanf("%lld%lld%lld", &f1,&f2,&n))
    {    
        //printf("%d\n", fast_mod(n));
        f1 = f1%MOD;
        f2 = f2%MOD;
        int ans = 0;
        if( n >= 6)
        {
        	ans = ((fast_mod(n-1) * f2))%MOD + (fast_mod(n-2)*f1)%MOD;
        	ans %= MOD;
        	int j = n-6;
        	if(j%2 == 0)
        	{
        		ans = (ans - (fast_mod(j/2+2)*fast_mod(j/2+2))%MOD + MOD)%MOD;
			}
			else
			{
				ans = (ans - (fast_mod(j/2+2)*fast_mod(j/2+3))%MOD + MOD)%MOD;
			}
		}
		else if (n >= 3)
		{
			ans = ((fast_mod(n-1) * f2))%MOD + (fast_mod(n-2)*f1)%MOD;
			ans = (ans + dfs(n-1) + MOD)%MOD;
		}
		else if(n == 2)
		{
			ans = f2;
		}
		else
		{
			ans = f1;
		}
		cout<<ans<<endl;
    }
    
}





sin(πx2)f(x+1)=f(x)+f(x−1)+sin⁡(πx2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值