算法分析与排序

  • A - Fibonacci (POJ - 3070)
    • 分析
    • 代码
  • B - Tr A (HDU - 1575)
    • 分析
    • 代码
  • C - A Simple Math Problem (HDU - 1757)
    • 分析
    • 代码
  • D - Recursive sequence (HDU - 5950)
    • 分析
    • 代码
  • E - ProjectEuler 48 (51Nod - 2182)
    • 分析
    • 代码
  • F - 求递推序列的第N项 (51Nod - 1126)
    • 分析
    • 代码
  • G - 人见人爱A^B (HDU - 2035)
    • 分析
    • 代码

网页链接:传送门
密码:hpucam

A - Fibonacci (POJ - 3070)

菲波那契数列是指这样的数列: 数列的第一个是0和第二个数是1,接下来每个数都等于前面2个数之和。 给出一个正整数a,要求菲波那契数列中第a个数的后四位是多少。
Input
多组数据 -1结束 范围1~10^9
Output
第x项的后4位

Sample Input Sample Output
0
9
999999999
1000000000
-1
0
34
626
6875

分析

这题要用到矩阵快速幂。
已知 数列的第一个是0和第二个数是1,接下来每个数都等于前面2个数之和,我们可以设成: f ( 0 ) = 0 , f ( 1 ) = 1 , f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2) f(0)=0,f(1)=1,f(n)=f(n−1)+f(n−2) 。
因此我们可以构建式子: [ f ( n + 1 ) f ( n ) ] = [ 1 1 1 0 ] [ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] n [ f ( 1 ) f ( 0 ) ] = [ 1 1 1 0 ] n [ 1 0 ] \left[ \begin{matrix} f(n+1) \\ f(n) \end{matrix} \right]= \left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right] \left[ \begin{matrix} f(n) \\ f(n-1) \end{matrix} \right]=\left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right]^{n} \left[ \begin{matrix} f(1) \\ f(0) \end{matrix} \right]=\left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right]^{n} \left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] [f(n+1)f(n)​]=[11​10​][f(n)f(n−1)​]=[11​10​]n[f(1)f(0)​]=[11​10​]n[10​]

因此,我们只需要计算 [ 1 1 1 0 ] n \left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right]^{n} [11​10​]n 的值,最后因为我们要的是 f ( n ) f(n) f(n) ,因此只需要输出 ( b . m [ 2 ] [ 1 ] + m o d ) % m o d (b.m[2][1]+mod)\%mod (b.m[2][1]+mod)%mod 或者 b . m [ 2 ] [ 1 ] % m o d b.m[2][1]\%mod b.m[2][1]%mod 就可以了。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=10000;   //要求后四位数,只需要对10000求余
struct node
{ll m[3][3];
};
node mul(node a,node b) //矩阵相乘
{node temp; //临时矩阵,存放a×b的结果memset(temp.m,0,sizeof(temp.m));for(int i=1;i<3;i++){for(int j=1;j<3;j++){for(int k=1;k<3;k++){temp.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;}}}return temp;
}
node qpower(node a,ll b)    //快速幂
{node temp;memset(temp.m,0,sizeof(temp.m));for(int i=1;i<3;i++)   //单位矩阵temp.m[i][i]=1;while(b){if(b&1)  temp=mul(temp,a);a=mul(a,a);b>>=1;}return temp;
}
int main()
{ll n;while(~scanf("%lld",&n)){if(n==-1)    break;node a,b; //a是最初方阵,b是结果方阵a.m[1][1]=1,a.m[1][2]=1;a.m[2][1]=1,a.m[2][2]=0;b=qpower(a,n);printf("%lld\n",(b.m[2][1]+mod)%mod);}return 0;
}

B - Tr A (HDU - 1575)

A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
Input
数据的第一行是一个T,表示有T组数据。
每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。
Output
对应每组数据,输出Tr(A^k)%9973。

Sample Input Sample Output
2
2 2
1 0
0 1
3 99999999
1 2 3
4 5 6
7 8 9
0
34
626
6875

分析

方阵是行数与列数相等的矩阵。对于方阵 A A A,只需要利用矩阵快速幂,计算 A k % 9973 A^k\%9973 Ak%9973 的值就可以了。

注意计算过程中也要 % 9973 \%9973 %9973,以免出现溢出现象。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=9973;
ll k,tr;
int T,n;
struct node
{ll m[15][15];
}res,ans;   //ans是结果方阵,res是初始方阵
node mul(node a,node b) //矩阵相乘
{node temp; //临时矩阵,存放a×b的结果memset(temp.m,0,sizeof(temp.m));for(int i=0;i<n;i++){for(int j=0;j<n;j++){for(int k=0;k<n;k++){temp.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;}}}return temp;
}
void qpower(int a,int b)    //快速幂
{for(int i=0;i<b;i++) //单位矩阵{for(int j=0;j<b;j++){if(i==j)    ans.m[i][j]=1;else ans.m[i][j]=0;}}while(a){if(a&1)   ans=mul(ans,res);res=mul(res,res);a>>=1;}
}
int main()
{cin>>T;while(T--){cin>>n>>k;for(int i=0;i<n;i++)   //储存初始方阵的值{for(int j=0;j<n;j++){cin>>res.m[i][j];}}qpower(k,n); //计算结果方阵tr=0;for(int i=0;i<n;i++)    //计算主对角线上各项的和tr=(tr+ans.m[i][i])%mod;cout<<tr%mod<<endl;}return 0;
}

C - A Simple Math Problem (HDU - 1757)

Lele now is thinking about a simple function f(x).
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 ∗ * ∗ f(x-1) + a1 ∗ * ∗ f(x-2) + a2 ∗ * ∗ f(x-3) + …… + a9 ∗ * ∗ f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*109 , m < 105 )
In the second line , there are ten integers represent a0 ~ a9.
Output
For each case, output f(k) % m in one line.

Sample Input Sample Output
10 9999
1 1 1 1 1 1 1 1 1 1
20 500
1 0 1 0 1 0 1 0 1 0
45
104

分析

题意:对于 f ( x ) = { x , x < 10 a 0 ∗ f ( x − 1 ) + a 1 ∗ f ( x − 2 ) + a 2 ∗ f ( x − 3 ) + … … + a 9 ∗ f ( x − 10 ) , x ≥ 10 f(x)=\begin{cases}x, x<10\\a_0 * f(x-1) + a_1 * f(x-2) + a_2 * f(x-3) + …… + a_9 * f(x-10),x≥10\end{cases} f(x)={x,x<10a0​∗f(x−1)+a1​∗f(x−2)+a2​∗f(x−3)+……+a9​∗f(x−10),x≥10​,且 a i ∈ 0 或 1 a_i∈0或1 ai​∈0或1 ,给你 k k k 和 m m m ,让你计算 f ( k ) % m f(k)\%m f(k)%m 的值。

为了提高效率,我们进行分类讨论。当输入的 k k k 的值 < 10 <10 <10时,直接输出 k % m k\%m k%m 的值。而对于 k ≥ 10 k≥10 k≥10 的情况,我们进行以下详细讨论:
f ( x ) = a 0 ∗ f ( x − 1 ) + a 1 ∗ f ( x − 2 ) + a 2 ∗ f ( x − 3 ) + … … + a 9 ∗ f ( x − 10 ) f(x)=a_0 * f(x-1) + a_1 * f(x-2) + a_2 * f(x-3) + …… + a_9 * f(x-10) f(x)=a0​∗f(x−1)+a1​∗f(x−2)+a2​∗f(x−3)+……+a9​∗f(x−10),由此我们可以构建式子:
[ f ( n ) f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) f ( n − 4 ) f ( n − 5 ) f ( n − 6 ) f ( n − 7 ) f ( n − 8 ) f ( n − 9 ) ] = [ a 0 a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 ] n − 9 [ f ( 9 ) f ( 8 ) f ( 7 ) f ( 6 ) f ( 5 ) f ( 4 ) f ( 3 ) f ( 2 ) f ( 1 ) f ( 0 ) ] = [ a 0 a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 ] n − 9 [ 9 8 7 6 5 4 3 2 1 0 ] \left[ \begin{matrix} f(n) \\ f(n-1) \\ f(n-2) \\ f(n-3) \\ f(n-4) \\ f(n-5) \\ f(n-6) \\ f(n-7) \\ f(n-8) \\ f(n-9) \end{matrix} \right]= \left[ \begin{matrix} a_0 & a_1 & a_2 & a_3 & a_4 & a_5 & a_6 & a_7 & a_8 & a_9 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{matrix} \right]^{n-9} \left[ \begin{matrix} f(9) \\ f(8) \\ f(7) \\ f(6) \\ f(5) \\ f(4) \\ f(3) \\ f(2) \\ f(1) \\ f(0) \end{matrix} \right]=\left[ \begin{matrix} a_0 & a_1 & a_2 & a_3 & a_4 & a_5 & a_6 & a_7 & a_8 & a_9 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{matrix} \right]^{n-9} \left[ \begin{matrix} 9 \\ 8 \\ 7 \\ 6 \\ 5 \\ 4 \\ 3 \\ 2 \\ 1 \\ 0 \end{matrix} \right] ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​f(n)f(n−1)f(n−2)f(n−3)f(n−4)f(n−5)f(n−6)f(n−7)f(n−8)f(n−9)​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​a0​100000000​a1​010000000​a2​001000000​a3​000100000​a4​000010000​a5​000001000​a6​000000100​a7​000000010​a8​000000001​a9​000000000​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​n−9⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​f(9)f(8)f(7)f(6)f(5)f(4)f(3)f(2)f(1)f(0)​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​a0​100000000​a1​010000000​a2​001000000​a3​000100000​a4​000010000​a5​000001000​a6​000000100​a7​000000010​a8​000000001​a9​000000000​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​n−9⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​9876543210​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​
因此,我们只需要先利用矩阵快速幂,解出 [ a 0 a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 ] n − 9 \left[ \begin{matrix} a_0 & a_1 & a_2 & a_3 & a_4 & a_5 & a_6 & a_7 & a_8 & a_9 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \end{matrix} \right]^{n-9} ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​a0​100000000​a1​010000000​a2​001000000​a3​000100000​a4​000010000​a5​000001000​a6​000000100​a7​000000010​a8​000000001​a9​000000000​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​n−9的值,再让结果矩阵的第一行与 [ 9 8 7 6 5 4 3 2 1 0 ] \left[ \begin{matrix} 9 \\ 8 \\ 7 \\ 6 \\ 5 \\ 4 \\ 3 \\ 2 \\ 1 \\ 0 \end{matrix} \right] ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡​9876543210​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤​逐个相乘求余后相加,就能够得到我们想要得到的 f ( n ) f(n) f(n) 的值。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=10;
ll k,m,sum;
struct node
{ll a[N][N];
}res,ans;   //ans是结果矩阵,res是初始方阵
node mul(node a,node b) //矩阵相乘
{node temp; //临时矩阵,存放a*b的结果memset(temp.a,0,sizeof(temp.a));for(int i=0;i<N;i++){for(int j=0;j<N;j++){for(int k=0;k<N;k++){temp.a[i][j]+=(a.a[i][k]*b.a[k][j])%m;}}}return temp;
}
void qpower(int a,int b)    //快速幂
{for(int i=0;i<N;i++) //单位矩阵{for(int j=0;j<N;j++){if(i==j)    ans.a[i][j]=1;else ans.a[i][j]=0;}}while(a){if(a&1)   ans=mul(ans,res);res=mul(res,res);a>>=1;}
}
int main()
{while(~scanf("%lld%lld",&k,&m)){memset(res.a,0,sizeof(res.a));   //清空初始矩阵for(int i=0;i<N;i++)  //给初始矩阵赋值{scanf("%d",&res.a[0][i]);}for(int i=1;i<N;i++){res.a[i][i-1]=1;}if(k<10)  printf("%lld\n",k%m); //如果k<10,那么f(k)的值已经确定是k了,因此可以直接求余计算并输出。else{qpower(k-9,N); //计算结果矩阵sum=0;for(int i=0;i<N;i++){sum+=ans.a[0][i]*(9-i)%m;}printf("%lld\n",sum%m);}}return 0;
}

D - Recursive sequence (HDU - 5950)

Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and i4. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right.
Input
The first line of input contains an integer t, the number of test cases. t test cases follow.
Each case contains only one line with three numbers N, a and b where N,a,b < 231 as described above.
Output
For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo 2147493647.

Sample Input Sample Output Hint
2
3 1 2
4 1 10
85
369
In the first case, the third number is 85 = 2 ∗ * ∗ 1十2十34.
In the second case, the third number is 93 = 2 ∗ * ∗ 1十1 ∗ * ∗ 10十34 and the fourth number is 369 = 2 ∗ * ∗ 10 十 93 十 44.

分析

题意:有递推式 f ( n ) = f ( n − 1 ) + 2 f ( n − 2 ) + n 4 , f ( 1 ) = a , f ( 2 ) = b f(n)=f(n-1)+2f(n-2)+n^4,f(1)=a,f(2)=b f(n)=f(n−1)+2f(n−2)+n4,f(1)=a,f(2)=b ,输入 n , a , b n,a,b n,a,b 的值,让你计算 f ( n ) f(n) f(n) 的值。

这题也是和前面的题一样,需要构建式子。 难点在于 n 4 n^4 n4 的构建。这里我们根据题目给的式子,我们还可以把它写成 f ( n + 1 ) = f ( n ) + 2 f ( n − 1 ) + ( n + 1 ) 4 , f ( 1 ) = a , f ( 2 ) = b f(n+1)=f(n)+2f(n-1)+(n+1)^4,f(1)=a,f(2)=b f(n+1)=f(n)+2f(n−1)+(n+1)4,f(1)=a,f(2)=b 。而 ( n + 1 ) 4 = n 4 + 4 n 3 + 6 n 2 + 4 n + 1 , ( n + 1 ) 3 = n 3 + 3 n 2 + 3 n + 1 , ( n + 1 ) 2 = n 2 + 2 n + 1 (n+1)^4=n^4+4n^3+6n^2+4n+1,(n+1)^3=n^3+3n^2+3n+1,(n+1)^2=n^2+2n+1 (n+1)4=n4+4n3+6n2+4n+1,(n+1)3=n3+3n2+3n+1,(n+1)2=n2+2n+1,我们就可以利用 n 4 , n 3 , n 2 , n 1 , n 0 n^4,n^3,n^2,n^1,n^0 n4,n3,n2,n1,n0 来构建式子:
[ f ( n ) f ( n − 1 ) ( n + 1 ) 4 ( n + 1 ) 3 ( n + 1 ) 2 ( n + 1 ) 1 ( n + 1 ) 0 ] = [ 1 2 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 4 6 4 1 0 0 0 1 3 3 1 0 0 0 0 1 2 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ] [ f ( n − 1 ) f ( n − 2 ) n 4 n 3 n 2 n 1 n 0 ] = [ 1 2 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 4 6 4 1 0 0 0 1 3 3 1 0 0 0 0 1 2 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ] n − 2 [ f ( 2 ) f ( 1 ) 3 4 3 3 3 2 3 1 3 0 ] \left[ \begin{matrix} f(n) \\ f(n-1) \\ (n+1)^4 \\ (n+1)^3 \\ (n+1)^2 \\ (n+1)^1 \\ (n+1)^0 \end{matrix} \right]= \left[ \begin{matrix} 1 & 2 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 4 & 6 & 4 & 1 \\ 0 & 0 & 0 & 1 & 3 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 2 & 1 \\ 0 & 0 & 0 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2) \\ n^4 \\ n^3 \\ n^2 \\ n^1 \\ n^0 \\ \end{matrix} \right]=\left[ \begin{matrix} 1 & 2 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 4 & 6 & 4 & 1 \\ 0 & 0 & 0 & 1 & 3 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 2 & 1 \\ 0 & 0 & 0 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{matrix} \right]^{n-2} \left[ \begin{matrix} f(2) \\ f(1) \\ 3^4 \\ 3^3 \\ 3^2 \\ 3^1 \\ 3^0 \\ \end{matrix} \right] ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​f(n)f(n−1)(n+1)4(n+1)3(n+1)2(n+1)1(n+1)0​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​1100000​2000000​1010000​0041000​0063100​0043210​0011111​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​f(n−1)f(n−2)n4n3n2n1n0​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​1100000​2000000​1010000​0041000​0063100​0043210​0011111​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​n−2⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​f(2)f(1)3433323130​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​
因此,我们只需要先利用矩阵快速幂,解出 [ 1 2 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 4 6 4 1 0 0 0 1 3 3 1 0 0 0 0 1 2 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ] n − 2 \left[ \begin{matrix} 1 & 2 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 4 & 6 & 4 & 1 \\ 0 & 0 & 0 & 1 & 3 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 2 & 1 \\ 0 & 0 & 0 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{matrix} \right]^{n-2} ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​1100000​2000000​1010000​0041000​0063100​0043210​0011111​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​n−2 的值之后,让结果矩阵的第一行分别与 [ b a 81 27 9 3 1 ] \left[ \begin{matrix} b \\ a \\ 81 \\ 27 \\ 9 \\ 3 \\ 1 \\ \end{matrix} \right] ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​ba8127931​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​ 相乘取余,就是我们想要的 f ( n ) f(n) f(n) 的值了。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=7;
const ll m=2147493647; //记得是ll
ll n,A,B,sum;
struct node
{ll a[N][N];
}res,ans;   //ans是结果矩阵,res是初始方阵
node mul(node a,node b) //矩阵相乘
{node temp; //临时矩阵,存放a*b的结果memset(temp.a,0,sizeof(temp.a));for(int i=0;i<N;i++){for(int j=0;j<N;j++){for(int k=0;k<N;k++){temp.a[i][j]=(temp.a[i][j]+a.a[i][k]*b.a[k][j])%m;}}}return temp;
}
void qpower(int a,int b)    //快速幂
{for(int i=0;i<b;i++) //单位矩阵{for(int j=0;j<b;j++){if(i==j)    ans.a[i][j]=1;else ans.a[i][j]=0;}}while(a){if(a&1)   ans=mul(ans,res);res=mul(res,res);a>>=1;}
}
int main()
{int T;scanf("%d",&T);while(T--){scanf("%lld%lld%lld",&n,&A,&B);res.a[0][0]=1,res.a[0][1]=2,res.a[0][2]=1,res.a[0][3]=0,res.a[0][4]=0,res.a[0][5]=0,res.a[0][6]=0;res.a[1][0]=1,res.a[1][1]=0,res.a[1][2]=0,res.a[1][3]=0,res.a[1][4]=0,res.a[1][5]=0,res.a[1][6]=0;res.a[2][0]=0,res.a[2][1]=0,res.a[2][2]=1,res.a[2][3]=4,res.a[2][4]=6,res.a[2][5]=4,res.a[2][6]=1;res.a[3][0]=0,res.a[3][1]=0,res.a[3][2]=0,res.a[3][3]=1,res.a[3][4]=3,res.a[3][5]=3,res.a[3][6]=1;res.a[4][0]=0,res.a[4][1]=0,res.a[4][2]=0,res.a[4][3]=0,res.a[4][4]=1,res.a[4][5]=2,res.a[4][6]=1;res.a[5][0]=0,res.a[5][1]=0,res.a[5][2]=0,res.a[5][3]=0,res.a[5][4]=0,res.a[5][5]=1,res.a[5][6]=1;res.a[6][0]=0,res.a[6][1]=0,res.a[6][2]=0,res.a[6][3]=0,res.a[6][4]=0,res.a[6][5]=0,res.a[6][6]=1;if(n==1)   printf("%lld\n",A%m);else if(n==2)  printf("%lld\n",B%m);else{qpower(n-2,N);  //计算结果矩阵sum=0;sum=(sum+ans.a[0][0]*B)%m;sum=(sum+ans.a[0][1]*A)%m;sum=(sum+ans.a[0][2]*81)%m;sum=(sum+ans.a[0][3]*27)%m;sum=(sum+ans.a[0][4]*9)%m;sum=(sum+ans.a[0][5]*3)%m;sum=(sum+ans.a[0][6]*1)%m;printf("%lld\n",sum%m);}}return 0;
}

E - ProjectEuler 48 (51Nod - 2182)

考虑求和
11+22+33+⋯+1010=10405071317
输入n,求
11+22+33+⋯+nn
对 1010 取模的结果。
Input
输入第一行组数T, 接下来T行,每行一个整数n。 (1 <= T <= 1000) (1 <= N <= 1000)
Output
对于每组数据,输出一个数,表示求和对10000000000取模的结果。

Sample Input Sample Output
4
1
10
100
1000
1
405071317
9027641920
9110846700

分析

这题因为一开始没有讲快速乘,所以卡了一段时间,然后在网上找了一篇还不错的博客,这里是链接,有机会再自己总结⑧。

因为每种快速乘的写法的时间复杂度都不一样,我这里就列了两种不同的写法。按这些写法都可以AC。

代码

  1. 第一种写法

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const ll maxn=1010;
    const ll MOD=1e10;
    int T,N;
    ll sum[maxn],cnt;
    ll ksc(ll x,ll y,ll mod)
    {ll z=(ld)x/mod*y;ll res=(ull)x*y-(ull)z*mod;return (res+mod)%mod;
    }
    ll qpow(ll x,ll y,ll mod)
    {ll res=1;while(y){if(y&1) res=ksc(res,x,mod);x=ksc(x,x,mod);y>>=1;}return res%mod;
    }
    int main()
    {scanf("%d",&T);while(T--){scanf("%d",&N);cnt=0;for(int i=1;i<=N;i++){cnt=(cnt+qpow(i,i,MOD)+MOD)%MOD;}printf("%lld\n",cnt);}return 0;
    }
    
  2. 第二种写法
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const ll maxn=1010;
    const ll MOD=1e10;
    int T,N;
    ll sum[maxn],cnt;
    ll ksc(ll x,ll y,ll mod)
    {ll res=0;while(y){if(y&1) res=(res+x)%mod;x=(x<<1)%mod;y>>=1;}return res%mod;
    }
    ll qpow(ll x,ll y,ll mod)
    {ll res=1;while(y){if(y&1) res=ksc(res,x,mod);x=ksc(x,x,mod);y>>=1;}return res%mod;
    }
    void init()
    {for(int i=1;i<maxn;i++){sum[i]=(sum[i-1]+qpow(i,i,MOD)+MOD)%MOD;}
    }
    int main()
    {scanf("%d",&T);init();while(T--){scanf("%d",&N);printf("%lld\n",sum[N]);}return 0;
    }
    

F - 求递推序列的第N项 (51Nod - 1126)

有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A ∗ * ∗ f(n - 1) + B ∗ * ∗ f(n - 2)) mod 7.
给出A,B和N,求f(n)的值。
Input
输入3个数:A,B,N。数字之间用空格分割。(-10000 <= A, B <= 10000, 1 <= N <= 10^9)
Output
输出f(n)的值。

Sample Input Sample Output
3 -1 5 6

分析

此题的题意题目写的挺清楚了,给定 A , B , N A,B,N A,B,N 的值,让你求出 f ( N ) f(N) f(N) 的值。
而对于 f ( n ) f(n) f(n) ,有: f ( n ) = { 1 , n = 1 或 2 ( A ∗ f ( n − 1 ) + B ∗ f ( n − 2 ) ) m o d 7 , n ≠ 1 或 2 f(n)=\begin{cases}1,n=1或2\\(A*f(n - 1)+B*f(n - 2)) mod 7,n≠1或2\end{cases} f(n)={1,n=1或2(A∗f(n−1)+B∗f(n−2))mod7,n​=1或2​
因此我们可以构建式子:
[ f ( n ) f ( n − 1 ) ] = [ A B 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ] = [ A B 1 0 ] n − 2 [ f ( 2 ) f ( 1 ) ] = [ A B 1 0 ] n − 2 [ 1 1 ] \left[ \begin{matrix} f(n) \\ f(n-1) \end{matrix} \right]= \left[ \begin{matrix} A & B \\ 1 & 0 \end{matrix} \right] \left[ \begin{matrix} f(n-1) \\ f(n-2) \end{matrix} \right]=\left[ \begin{matrix} A & B \\ 1 & 0 \end{matrix} \right]^{n-2} \left[ \begin{matrix} f(2) \\ f(1) \end{matrix} \right]=\left[ \begin{matrix} A & B \\ 1 & 0 \end{matrix} \right]^{n-2} \left[ \begin{matrix} 1 \\ 1 \end{matrix} \right] [f(n)f(n−1)​]=[A1​B0​][f(n−1)f(n−2)​]=[A1​B0​]n−2[f(2)f(1)​]=[A1​B0​]n−2[11​]
所以,我们可以利用矩阵快速幂,求出 [ A B 1 0 ] n − 2 \left[ \begin{matrix} A & B \\ 1 & 0 \end{matrix} \right]^{n-2} [A1​B0​]n−2的值, f ( n ) f(n) f(n) 的值就是结果矩阵的第一行元素之和并对 7 7 7 求余。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int MOD=7;
const int maxn=10;
ll A,B,N;
ll k,m,sum;
struct node
{ll m[3][3];
}res,ans;   //ans是结果矩阵,res是初始方阵
node mul(node a,node b) //矩阵相乘
{node temp; //临时矩阵,存放a×b的结果memset(temp.m,0,sizeof(temp.m));for(int i=1;i<3;i++){for(int j=1;j<3;j++){for(int k=1;k<3;k++){temp.m[i][j]+=(a.m[i][k]*b.m[k][j])%MOD;}}}return temp;
}
void qpower(int a,int b)    //快速幂
{for(int i=1;i<b;i++) //单位矩阵{for(int j=1;j<b;j++){if(i==j)    ans.m[i][j]=1;else ans.m[i][j]=0;}}while(a){if(a&1)   ans=mul(ans,res);res=mul(res,res);a>>=1;}
}
int main()
{scanf("%lld%lld%lld",&A,&B,&N);res.m[1][1]=A,res.m[1][2]=B;res.m[2][1]=1,res.m[2][2]=0;if(N==1 || N==2)  printf("1");else{qpower(N-2,3);printf("%lld",(ans.m[1][1]+ans.m[1][2]+MOD)%MOD);}return 0;
}

G - 人见人爱A^B (HDU - 2035)

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。

Sample Input Sample Output
2 3
12 6
6789 10000
0 0
8
984
1

分析

这题我之前的题解写过了,这里放一下链接。
直接套快速幂的模板就可。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
ll A,B;
ll qpow(ll x,ll y,ll mod)   //快速幂板子
{ll res=1;while(y){if(y&1) res=(res*x)%mod;x=(x*x)%mod;y>>=1;}return res;
}
int main()
{while(~scanf("%lld%lld",&A,&B)){if(A==0 && B==0) break;printf("%lld\n",qpow(A,B,1000)%1000);}return 0;
}

2020.7.20【算协集训】矩阵快速幂相关推荐

  1. 2020.8.8【算协集训】[第4次积分赛]

    第4次积分赛 Problem A. 胡图图的数学难题 分析 代码 Problem B. 胡图图和小美 分析 代码 Problem C. 胡图图公司大整改 Problem D. 胡图图偷吃记 分析 代码 ...

  2. 矩阵问题入门(矩阵乘法and矩阵快速幂)acm寒假集训日记22/1/15

    今天凌晨3点才睡,没想到通过看小说抑制玩游戏,反而看小说的时间更长. u1s1:那小说太刺激了,晚上看很有感觉,风吹草动我就会猛地看过去(类似茄子说柜子动了,哈哈),真TM(语气词)练胆量!!!..Q ...

  3. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  4. 一文彻底搞懂快速幂(原理、实现、矩阵快速幂)

    前言 大家好,我是bigsai,之前有个小老弟问到一个剑指offer一道相关快速幂的题,这里梳理一下讲一下快速幂! 快速幂是什么? 顾名思义,快速幂就是快速算底数的n次幂.你可能疑问,求n次幂算n次叠 ...

  5. HDU - 6185 Covering(暴搜+递推+矩阵快速幂/杜教BM)

    题目链接:点击查看 题目大意:规定宽度为4,给定长度为n,求用1*2和2*1的瓷砖,将其完全铺满能有多少种方法. 分析:自从学会了矩阵快速幂之后,看到1e18的数据量都会下意识的往递推上面想,但是以前 ...

  6. [BZOJ3583]杰杰的女性朋友(矩阵快速幂)

    杰杰的女性朋友 时间限制:10s      空间限制:256MB 题目描述 杰杰是魔法界的一名传奇人物.他对魔法具有深刻的洞察力,惊人的领悟力,以及令人叹为观止的创造力.自从他从事魔法竞赛以来,短短几 ...

  7. 快速幂或者矩阵快速幂

    快速幂或者矩阵快速幂在算大指数次方时是很高效的,他的基本原理是二进制,下面的A可以是一个数也可以是一个矩阵(本文特指方阵),若是数就是快速幂算法,若是矩阵就是矩阵快速幂算法,用c++只需把矩阵设成一个 ...

  8. 二分幂,快速幂,矩阵快速幂,快速乘

    前言 二分幂,快速幂,矩阵快速幂在算大指数次方时是很高效的. 求 a^n 的值是多少?n是1到10^18次方的一个整数. 求一个数的n次方,朴素的算法就是直接for循环,一遍一遍的乘,a*a*a*a* ...

  9. L. Poor God Water(ACM-ICPC 2018 焦作赛区网络预赛,ac自动机+矩阵快速幂 或 BM线性递推)

    描述 God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells hi ...

最新文章

  1. 如何在Fragment中使用findViewById
  2. 矩阵相关概念的物理意义
  3. 融资 2000 万美元后,他竟将核心代码全开源,这……能行吗?
  4. c++ 利用boost 实现文件操作
  5. python 外部程序 交互_使用Python与其他程序交互
  6. [book]道法自然
  7. GB4208中规定的外壳防护等级IP
  8. 搭建Hexo博客(一)-创建Hexo环境
  9. 编译原理----词法分析程序----python语言版
  10. jdk8新特性(接口新特性、lambda表达式、方法引用、函数式接口、Stream流)和单例设计模式
  11. ubuntu虚拟机安装Gitlab后出现“Whoops, GitLab is taking too much time to respond.”
  12. 汇编程序:成绩分段统计
  13. 彻底删除mysql server 2005_sql2005卸载工具(sql server 2005卸载工具)
  14. 如何打开.DAT格式的测风数据?
  15. 17期-什么是MySQL数据库?看这一篇干货文章就够了!
  16. Java--配置环境变量
  17. Camera Self-Calibration: Theory and Experiments
  18. 《无人驾驶》-了解无人驾驶最佳读物
  19. 注意力缺陷/多动障碍和睡眠障碍之间有什么联系?基于大规模队列多模态研究
  20. 经典面试题:CSS定位知识及小盒子套大盒子的方法

热门文章

  1. IDEA(jetbrain通用)优雅级使用教程
  2. AWS托管AD + Yearning配置LDAP认证登录
  3. 星际特攻队java_星际特攻队手游
  4. 中专学的幼师大专想改专业学计算机可以吗,我是学幼师专业的,但是想改行,不知道改什么好...
  5. JVM编译优化技术:公共子表达式消除。
  6. 【matlab excel数据相互导入】matlab数据导至excel,excel数据导至matlab
  7. 【百度地图系列】规划驾车路线和途径点及判断车辆路线偏移
  8. 现在想拿到20k的高薪offer,到底是不是痴人说梦
  9. LeetCode 160. 相交链表(c++实现)
  10. OpenMP编译器指令