POJ 3233 快速幂和二分。。。基本上是别人的代码,自己改动一些,不过收获很大。

借鉴http://www.cnblogs.com/ACShiryu/archive/2011/08/09/poj3233.html
  1  /* 这道题目借鉴他人的思路和代码,很有收获
  2   先看下面这个快速幂求余的运算
  3 递归用二分法,每个过程都求余。
  4 long exp_mod(long a,long n,long b)
  5 {
  6     long t;
  7     if(n==0) return 1%b;
  8     if(n==1) return a%b;
  9     t=exp_mod(a,n/2,b);
 10     t=t*t%b;
 11     if((n&1)==1) t=t*a%b;
 12     return t;
 13 }
 14 本题用了两次二分的思想,一次用于求A^K,第二次用于求 (1+A^(k/2))*(A + A^2 + A^3 + … + A^(k/2))
 15 */
 16 
 17 
 18 #include<iostream>
 19 #include<stdio.h>
 20 using namespace std;
 21 //=======================================================
 22 int n,m,k;
 23 struct Point//定义结构体更加方便,用数组时结构体有大作用的
 24 {
 25      int a[32][32];
 26      void init()
 27      {
 28          memset(a,0,sizeof(a));
 29          for(int i=1;i<=32;++i)
 30          {
 31              a[i][i]=1;
 32          }
 33      }
 34 };
 35 //=======================================================
 36 Point mul(Point x,Point y)//乘法运算
 37 {
 38     Point z;
 39     for(int i=1;i<=n;++i)
 40     {
 41         for(int j=1;j<=n;++j)
 42         {
 43             int sum=0;
 44             for(int k=1;k<=n;++k)
 45             {
 46                 sum+=((x.a[i][k]*y.a[k][j])%m);//每次都求余
 47                 z.a[i][j]=(sum%m);//这时也要求余。。。。。。
 48             }
 49         }
 50     }
 51     return z;
 52 }
 53 
 54 Point add(Point p,Point q)//矩阵加法运算
 55 {
 56     Point c;
 57     for(int i=1;i<=n;++i)
 58     {
 59         for(int j=1;j<=n;++j)
 60         {
 61             c.a[i][j]=((p.a[i][j]+q.a[i][j])%m);//记得求余
 62         }
 63     }
 64     return c;
 65 }
 66 
 67 void display(Point p)//打印函数
 68 {
 69     int i,j;
 70     for( i=1;i<=n;++i)
 71     {
 72         for(j=1;j<=n-1;++j)
 73         {
 74             cout<<p.a[i][j]<<" ";//注意格式“ ”问题
 75         }
 76         if(j==n)cout<<p.a[i][j]<<endl;
 77         
 78     }
 79 }
 80 
 81 Point maxtrimul(Point s,int k)//用递归定义实现快速幂的乘法
 82 {
 83     Point ans;//用来存放结果的
 84     ans.init();
 85     if(k==1)return s;
 86     ans=maxtrimul(s,k>>1);//每次二分
 87     ans=mul(ans,ans);
 88     if(k&1//奇数时再乘一次
 89     {
 90         ans=mul(s,ans);
 91     }
 92     return ans;
 93   
 94 }
 95 
 96 Point maxtrisum(Point s,int k)
 97 {
 98     if(k==1)return s;
 99        Point ans;//用来保存答案
100     ans.init();
101     ans=add(ans,maxtrimul(s,k>>1));
102     ans=mul(ans,maxtrisum(s,k>>1));
103     if(k&1)//奇数时
104     {
105         ans=add(ans,maxtrimul(s,k));
106     }
107     return ans;
108 
109 }
110 
111 int main()                                                                                                                                                                                                     
112 {
113     cin>>n>>k>>m;
114     Point s;
115     for(int i=1;i<=n;++i)
116     {
117         for(int j=1;j<=n;++j)
118         {
119             cin>>s.a[i][j];
120         }
121     }
122     s=maxtrisum(s,k);
123     display(s);
124  
125 }
126 

posted on 2011-11-27 10:58 四也 阅读(190) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜