CSU1516矩阵快速幂+费马小定理

  通过这个题真的学到了不少东西,最起码矩阵快速幂算是入门了,普通快速幂也彻底明白了(以前都是打模板),了解了费马小定理

  关键点 求(a^fib[b])%p 的值其中p是素数,0<a<p, b在int范围内

  先假设fib[b]>p-1 那么上式

  (a^fib[b])%p = (a^(p-1)*a^(p-1)*....*a^(p-1)*a^m)%p

  (这里 m = fib[b]%(p-1))

  由于p是素数且a<p那么gcd(a,p)=1,所以由费小可得(a^(p-1))%p=1

  那上式就 = (a^(fib[b]%(p-1)))%p

  然后fib[b]%(p-1)可以用矩阵快速幂求得

  最后在用普通的快速幂就可以求得(a^m)%p

  得到了这些剩下的就只是一个区间dp了

  一时着急写出来,代码写的很丑,LL和int到处乱定义。。。

  下面是运行结果,时限2s,有点险。还有1s过的。。。

3 105459 round_0 1572 KB 1860 MS C++ 2109 B 2015-04-06 01:51:32
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 105;
 7 const int INF = 0x3f3f3f3f;
 8 typedef long long LL;
 9 int a[maxn],b[maxn];
10 int n;
11 LL p;
12 LL sum[maxn],dp[maxn][maxn];
13 struct node
14 {
15     LL a[2][2];
16     node ()
17     {
18         a[0][0] = a[1][0] = a[0][1] = 1;
19         a[1][1] = 0;
20     }
21 };
22 node mul(node A,node B)
23 {
24     node ans;
25     for(int i = 0;i<2;++i)for(int j = 0;j<2;++j)
26     {
27         ans.a[i][j] = 0;
28         for(int k = 0;k<2;++k)ans.a[i][j] = (ans.a[i][j]+A.a[i][k]*B.a[k][j])%(p-1);
29     }
30     return ans;
31 }
32 LL mypow(LL x,LL m,LL mod)
33 {
34     LL ret = 1;
35     while(m)
36     {
37         if(m&1)ret = (ret*x)%mod;
38         x = (x*x)%mod;
39         m/=2;
40     }
41     return ret;
42 }
43 int fib(int x)
44 {
45     node ans,s;
46     while(x)
47     {
48         if(x&1)ans = mul(ans,s);
49         s = mul(s,s);
50         x/=2;
51     }
52     return ans.a[1][0]%(p-1);
53 }
54 int solve(int x)
55 {
56     int m = fib(b[x]-1);
57     return mypow(a[x],m,p);
58 }
59 LL gcd(LL x,LL y)
60 {
61     return y?gcd(y,x%y):x;
62 }
63 int main()
64 {
65 //    freopen("in.txt","r",stdin);
66     int kase = 1;
67     while(cin>>n>>p)
68     {
69         for(int i = 1;i<=n;++i)for(int j = 1;j<=n;++j)dp[i][j] = i==j?0:INF;
70         for(int i = 1;i<=n;++i)scanf("%d",a+i);
71         for(int i = 1;i<=n;++i)scanf("%d",b+i);
72         for(int i = 1;i<=n;++i)a[i] = solve(i);
73
74         sum[0] = 0;sum[1] = a[1];
75         for(int i = 2;i<=n;++i)sum[i] = sum[i-1]+(LL)a[i];
76         printf("case %d: ",kase++);
77         if(n==1){printf("0\n");continue;}
78         for(int r = 2;r<=n;++r)for(int i = 1;i<=n-r+1;++i)
79         {
80             int j = i+r-1;
81             for(int k = i;k<j;++k)
82                 dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+gcd(sum[k]-sum[i-1],sum[j]-sum[k-1]));
83         }
84         cout<<dp[1][n]<<endl;
85     }
86     return 0;
87 }

  

时间: 2024-10-23 04:26:24

CSU1516矩阵快速幂+费马小定理的相关文章

HDU 4549 M斐波那契数列 ( 矩阵快速幂 + 费马小定理 )

HDU 4549 M斐波那契数列 (  矩阵快速幂 + 费马小定理  ) 题意:中文题,不解释 分析:最好的分析就是先推一推前几项,看看有什么规律 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; #define CLR( a, b ) memset( a, b, sizeof(a) ) #define MOD 100000

hdu 4549 (矩阵快速幂+费马小定理)

题意:已知F0=a,F1=b,Fn=Fn-1*Fn-2,给你a,b,n求Fn%1000000007的值 思路:我们试着写几组数 F0=a F1=b F2=a*b F3=a*b2 F4=a2*b3 F5=a3*b5 我们发现a,b的系数其实是斐波那契数列,我们只需用矩阵快速幂求出相应系数就行,但是 这个系数随着增长会特别大,这时我们需要利用费马小定理进行降幂处理 费马小定理 ap-1≡1(mod p) 代码: #include <iostream> #include <cmath>

hdu 4549 M斐波那契数列(快速幂 矩阵快速幂 费马小定理)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4549: 题目是中文的很容易理解吧.可一开始我把题目看错了,这毛病哈哈. 一开始我看错题时,就用了一个快速幂来解,不用说肯定wa,看题目的通过率也不高,我想会不会有啥坑啊.然而我就是那大坑,哈哈. 不说了,直接说题吧,先讨论k=1,2,3;时的解.这应该会解吧,不多说了: 从第四项开始f(4)=a^1+b^2;f(5)=a^2+b^3;f(6)=a^3+b^5......; 看出来了吧,a上的指数成斐波

HDU 4549 M斐波那契数列(矩阵快速幂&amp;费马小定理)

ps:今天和战友聊到矩阵快速幂,想到前几天学长推荐去刷矩阵专题,挑了其中唯一一道中文题,没想到越过山却被河挡住去路... 题目链接:[kuangbin带你飞]专题十九 矩阵 R - M斐波那契数列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u 题意 Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2]

M斐波那契数列(矩阵快速幂+费马小定理)

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1672    Accepted Submission(s): 482 Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a,

hdu 4549 M斐波拉契 (矩阵快速幂 + 费马小定理)

Problem DescriptionM斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input输入包含多组测试数据:每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,

hdu4549矩阵快速幂+费马小定理

转移矩阵很容易求就是|0  1|,第一项是|0| |1  1|             |1| 然后直接矩阵快速幂,要用到费马小定理 :假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p).即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1(这东西贡献了我8次wa) 对矩阵进行取余的时候余mod-1,因为矩阵求出来是要当作幂的,就是a^b%p=a^(b%(p-1))%p #include<map> #includ

hdu-5667 Sequence(矩阵快速幂+费马小定理+快速幂)

题目链接: Sequence Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Holion August will eat every thing he has found. Now there are many foods,but he does not want to eat all of them at once,so he fi

HDU4549 M斐波那契数列(矩阵快速幂+费马小定理)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下:F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 )现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据:每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可