hdu 3221 Brute-force Algorithm(高速幂取模,矩阵高速幂求fib)

hdu 3221 Brute-force Algorithm(高速幂取模,矩阵高速幂求fib)

大家好,又见面了,我是全栈君。

http://acm.hdu.edu.cn/showproblem.php?pid=3221

一晚上搞出来这么一道题。。Mark。


给出这么一个程序。问funny函数调用了多少次。

我们定义数组为所求:f[1] = a,f[2] = b, f[3] = f[2]*f[3]……f[n] = f[n-1]*f[n-2]。相应的值表示也可为a^1*b^0%p。a^0*b^1%p,a^1*b^1%p,…..a^fib[n-3]*b^fib[n-2]%p。即a,b的指数从n=3以后与fib数列一样。


由于n非常大。fib[n]也想当大。

a^fib[n]%p能够利用a^fib[n]%p = a^(fib[n]%phi[p]+phi[p])%p进行降幂,条件时fib[n]>=phi[p]。求fib[n]%phi[p]能够构造矩阵。利用矩阵高速幂求fib[n]%phi[p]。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define C 240
#define S 20
using namespace std;
const int maxn = 110;

struct matrix
{
    LL mat[3][3];
    void init()
    {
        memset(mat,0,sizeof(mat));
        for(int i = 0; i < 2; i++)
            mat[i][i] = 1;
    }
} m;

LL a,b,p,n,phi_p;
LL fib[10000000];

//phi[p]
LL Eular(LL num)
{
    LL res = num;
    for(int i = 2; i*i <= num; i++)
    {
        if(num%i == 0)
        {
            res -= res/i;
            while(num%i == 0)
                num /= i;
        }
    }
    if(num > 1)
        res -= res/num;
    return res;
}
//矩阵相乘
matrix mul_matrix(matrix x, matrix y)
{
    matrix ans;
    memset(ans.mat,0,sizeof(ans.mat));
    for(int i = 0; i < 2; i++)
    {
        for(int k = 0; k < 2; k++)
        {
            if(x.mat[i][k] == 0) continue;
            for(int j = 0; j < 2; j++)
            {
                ans.mat[i][j] = (ans.mat[i][j] + x.mat[i][k]*y.mat[k][j])%phi_p;
            }
        }
    }
    return ans;
}
//a^t%phi_p
LL pow_matrix(LL t)
{
    matrix a,b;
    a.mat[0][0] = a.mat[0][1] = a.mat[1][0] = 1;
    a.mat[1][1] = 0;
    b.init();
    while(t)
    {
        if(t&1)
            b = mul_matrix(a,b);
        a = mul_matrix(a,a);
        t >>= 1;
    }
    return b.mat[0][0];
}
//a^t%p
LL pow(LL a, LL t)
{
    LL res = 1;
    a %= p;
    while(t)
    {
        if(t&1)
            res = res*a%p;
        a = a*a%p;
        t >>= 1;
    }
    return res;
}
//a^fib[t]%p转化为a^(fib[t]%phi[p]+phi[p])%p,fib[t] >= phi[p]。
LL solve(LL a, LL t)
{
    fib[0] = 1;
    fib[1] = 1;
    int i;
    for(i = 2; i <= t; i++)
    {
        fib[i] = fib[i-1] + fib[i-2];
        if(fib[i] >= phi_p)
            break;
    }
    if(i <= t) //当满足条件fib[t] >= phi[p]时,进行降幂
    {
        LL c = pow_matrix(t) + phi_p;
        return pow(a,c);
    }
    else
        return pow(a,fib[t]);
}

int main()
{
    int test;
    scanf("%d",&test);
    for(int item = 1; item <= test; item++)
    {
        scanf("%lld %lld %lld %lld",&a,&b,&p,&n);
        printf("Case #%d: ",item);
        if(n == 1)
        {
            printf("%lld\n",a%p);
            continue;
        }
        if(n == 2)
        {
            printf("%lld\n",b%p);
            continue;
        }
        if(n == 3)
        {
            printf("%lld\n",a*b%p);
            continue;
        }
        if(p == 1)
        {
            printf("0\n");
            continue;
        }
        phi_p = Eular(p);
        LL res = solve(a,n-3)*solve(b,n-2)%p;
        printf("%lld\n",res);
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116402.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • window清理系统垃圾文件代码

    window清理系统垃圾文件代码创建一个txt,后缀改为.bat,文件名自己取,但是要知道这个文件是拿来清理系统垃圾的。代码如下:@echooffpauseecho正在清理系统垃圾文件,请稍等……del/f/s/q%systemdrive%\*.tmpdel/f/s/q%systemdrive%\*._mpdel/f/s/q%systemdrive%\*.logdel/f…

    2022年6月18日
    19
  • python开发oa办公系统_python web开发框架

    python开发oa办公系统_python web开发框架https://www.odoo.com/zh_CN

    2025年7月5日
    0
  • 蓝桥杯入门训练Fibonacci数列 C语言

    蓝桥杯入门训练Fibonacci数列 C语言Fibonacci 数列 C 语言问题描述 Fibonacci 数列的递推公式为 Fn Fn 1 Fn 2 其中 F1 F2 1 当 n 比较大时 Fn 也非常大 现在我们想知道 Fn 除以 10007 的余数是多少 输入格式输入包含一个整数 n 输出格式输出一行 包含一个整数 表示 Fn 除以 10007 的余数 说明 在本题中 答案是要求 Fn 除以 10007 的余数 因此我们只要能算出这个余数即可 而不需要先计

    2025年6月25日
    0
  • 第一范式,第二范式,第三范式,BCNF范式理解

    第一范式,第二范式,第三范式,BCNF范式理解第一范式、第二范式、第三范式参考了https://www.zhihu.com/question/24696366https://www.cnblogs.com/lca1826/p/6601395.html基础知识实体:现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也…

    2022年5月10日
    32
  • pycharm设置背景色及字体_pycharm如何改变背景

    pycharm设置背景色及字体_pycharm如何改变背景设置背景变黑file->setting->appearance&behavior->appearance->在theme处选择darcula设置字体大小还是看百度的比较清晰http://jingyan.baidu.com/article/76a7e409de785efc3a6e1557.html打开pycharm,点击file->setting->a

    2022年8月25日
    5
  • mac版navicat激活码【2021最新】

    (mac版navicat激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月27日
    247

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号