zoukankan      html  css  js  c++  java
  • 【HDU3802】【降幂大法+矩阵加速+特征方程】Ipad,IPhone

    Problem Description
    In ACM_DIY, there is one master called “Lost”. As we know he is a “-2Dai”, which means he has a lot of money.
      

    Well, Lost use Ipad and IPhone to reward the ones who solve the following problem.
      

    In this problem, we define F( n ) as :
      

    Then Lost denote a function G(a,b,n,p) as

    Here a, b, n, p are all positive integer!
    If you could tell Lost the value of G(a,b,n,p) , then you will get one Ipad and one IPhone!
     
    Input
    The first line is one integer T indicates the number of the test cases. (T <= 100)
    Then for every case, only one line containing 4 positive integers a, b, n and p.
    (1 ≤a, b, n, p≤2*109 , p is an odd prime number and a,b < p.)
     
    Output
    Output one line,the value of the G(a,b,n,p) .
     
    Sample Input
    4 2 3 1 10007 2 3 2 10007 2 3 3 10007 2 3 4 10007
     
    Sample Output
    40 392 3880 9941
     
    Author
    AekdyCoin
     
    Source
     
    Recommend
    notonlysuccess   |   We have carefully selected several similar problems for you:  3805 3800 3801 3803 3804
    【分析】
    不知道怎么回事...跟网上的程序对拍了好像没错,怎么过不了...应该是有些比较坑的点....
    不错的一道题目,前面的两项不说了,后面的那一项可以把二次方弄进去,然后变成一个用韦达定理做一个逆运算得到特征方程。
    然后就有递推式了,然后就可以矩阵加速了。
    然后因为幂实在是太大了,然后上降幂大法,然后没了。
    其实还涉及到二次剩余的理论,如果前面没有那两个式子答案就错了....因为刚好是那两个式子,让不能用降幂大法的情况变成0...
      1 /*
      2 五代李煜
      3 《相见欢·林花谢了春红》
      4 林花谢了春红,太匆匆。无奈朝来寒雨晚来风。
      5 胭脂泪,相留醉,几时重。自是人生长恨水长东。
      6 */ 
      7 #include <iostream>
      8 #include <cstdio>
      9 #include <ctime>
     10 #include <cmath>
     11 #include <algorithm>
     12 #include <cstring>
     13 #include <string>
     14 #include <map>
     15 #include <set>
     16 #include <vector> 
     17 #define LOCAL
     18 const int MAXN = 1000 + 10;
     19 const int INF = 0x7fffffff;
     20 using namespace std;
     21 typedef long long ll;
     22 ll mod;//代表取模的数字
     23 ll check, a, b, n, p;
     24 struct Matrix{
     25        ll num[5][5];
     26        //Matrix(){memset(num, 0, sizeof(num));}
     27 };
     28 //为了防止和第一种矩阵乘法搞混 
     29 Matrix Mod(Matrix A, Matrix B, ll k){
     30      if (k == 0){//代表两种不同的乘法 
     31         Matrix c;
     32         memset(c.num, 0, sizeof (c.num));
     33         for (ll i = 1; i <= 2; i++)
     34         for (ll j = 1; j <= 2; j++)
     35         for (ll k = 1; k <= 2; k++){
     36             ll tmp = (A.num[i][k] * B.num[k][j]);
     37             if (check) tmp %= (p - 1);
     38             c.num[i][j] += tmp;
     39             if (check) c.num[i][j] %= (p - 1);
     40         }
     41         //一旦大于了p-1代表当前出现的斐波那契数列会大于phi(p),可以使用降幂大法 
     42         if ((c.num[1][1] + c.num[1][2]) > (p - 1)) check = 1; 
     43         return c; 
     44      }else if (k == 1){
     45            Matrix C;
     46            memset(C.num, 0, sizeof(C.num));
     47            for (ll i = 1; i <= 2; i++)
     48            for (ll j = 1; j <= 2; j++)
     49            for (ll k = 1; k <= 2; k++) {
     50                C.num[i][j] += (A.num[i][k] * B.num[k][j]) % p;
     51                C.num[i][j] = ((C.num[i][j] % p) + p) % p;
     52            }         
     53            return C;
     54      }
     55 }
     56 //得到第x位的斐波那契数,也就是获得指数
     57 Matrix Matrix_pow(Matrix A, ll x, ll k){
     58        if (x == 1) return A;
     59        Matrix tmp = Matrix_pow(A, x / 2, k);
     60        if (x % 2 == 0) return Mod(tmp, tmp, k);
     61        else return Mod(Mod(tmp, tmp, k), A, k);
     62 } 
     63 ll get(ll x){
     64      if (x == 0) return 1;
     65      else if (x == 1) return 1;
     66      Matrix A, B;
     67      A.num[1][1] = 1; A.num[1][2] = 1;
     68      A.num[2][1] = 1; A.num[2][2] = 0;
     69      x--;//为真实的需要乘的次数
     70      if (x == 0) return 1;
     71      B = Matrix_pow(A, x, 0);
     72      if (B.num[1][1] + B.num[1][2] > (p - 1)) check = 1;
     73      if (check == 0) return B.num[1][1] + B.num[1][2];
     74      else return (B.num[1][1] + B.num[1][2]) % (p - 1) + p - 1;
     75 }
     76 //有了a,b,pos就可进行矩阵加速了 
     77 ll cal(ll a, ll b, ll pos){
     78     if (pos == 0) return 2 % p;
     79     else if (pos == 1) return  (2 * (a + b)) % p;
     80     Matrix A;
     81     A.num[1][1] = (2 * (a + b)) % p; A.num[1][2] = (((-(a - b) * (a - b)) % p) + p) % p;
     82     A.num[2][1] = 1; A.num[2][2] = 0;
     83     pos--;
     84     Matrix B;
     85     B = Matrix_pow(A, pos, 1);
     86     return (B.num[1][1] * A.num[1][1]) % p + (B.num[1][2] * 2) % p;
     87 }
     88 ll pow(ll a, ll b){
     89     if (b == 0) return 1 % p;
     90     if (b == 1) return a % p;
     91     ll tmp = pow(a, b / 2);
     92     if (b % 2 == 0) return (tmp * tmp) % p;
     93     else return (((tmp * tmp) % p) * a) % p; 
     94 }
     95 
     96 int main(){
     97     int T;
     98     scanf("%d", &T);
     99     while (T--){
    100           //for (int i = 1; i ,=)
    101           scanf("%lld%lld%lld%lld", &a, &b, &n, &p);
    102           check = 0;//判断f(n)是否大于p 
    103           ll pos = get(n);
    104           ll Ans = cal(a, b, pos);
    105           ll f1, f2;
    106           f1 = (pow(a, (p - 1) / 2) + 1) % p;
    107           f2 = (pow(b, (p - 1) / 2) + 1) % p;
    108           Ans = (((f1 * f2) % p) * Ans) % p;
    109           printf("%lld
    ", Ans);
    110     }
    111     //p = 0x7fffffff;
    112     //printf("%lld", get(5));
    113     //for (int i = 0; i <= 10; i++) printf("%lld
    ", get(i));
    114     return 0;
    115 }
    View Code
  • 相关阅读:
    DataGridView 移动行
    DataGridView 显示提示信息
    模块和类的区别
    C# 流总结
    很口语I'm on my way
    读书笔记_Effective_C++_条款二十三:宁以nonmember、nonfriend替换member函数
    PDB文件:每个开发人员都必须知道的
    qq农场,数据抓包分析,实现源码,图片讲解
    连连看外挂消去算法分析
    关于“服务器提交了协议冲突. Section=ResponseStatusLine"问题请
  • 原文地址:https://www.cnblogs.com/hoskey/p/4354052.html
Copyright © 2011-2022 走看看