CodeForces 185A 快速幂

  一开始找矩阵快速幂的题来做时就看到了这题,题意就是让你求出如图所示的第n个三角形中指向向上的小三角形个数。从图中已经很容易看出递推关系了,我们以f[n]表示第n个大三角形中upward的小三角形个数,g[n]表示第n个大三角形中downward的小三角形个数,然后,递推关系就是:

  f[n]= 3*f[n-1]+1*g[n-1];

  g[n]= 3*g[n-1]+1*f[n-1];

其中f[0]=1,g[0]=0(一开始的纯三角形是从n=0开始的),然后……就没有然后了,直觉上感觉f[n]很难表示成只含有f[i]的式子,一时没想到该如何再和矩阵联系起来了(实际上两个不同的变量还是能构造出矩阵出来的:[ f(n), g(n) ]T= [ [3,1], [1,3] ]* [ f(n-1), g(n-1) ]T 即可,该矩阵就是 [ [3,1], [1,3] ]T,在这里写矩阵毕竟很不方便,自己在草稿纸上写出来看看吧,更直观),当时一时脑子发热没往这个方向去想,于是便转向了第二个思路。

  我再次观察了图发现它的确很有规律,无论是f[n]还是g[n]都是 1+2+3+……+k 的和嘛,k就是大三角形的层数,而层数也很有规律,第n个三角形的层数是前一个的两倍(也不难看出,因为每个子三角形每次都划分为两层),所以k= 2n,所以f[n]= (1+2n)*2n-1,g[n]也很容易表示出来,不过此时已经不需要g[n]了,之后,便是一个简简单单的裸快速幂即可!

 1 #include<cstdio>
 2 typedef long long LL;
 3 const LL mod= 1000000007;
 4
 5 LL quick_mod(LL a, LL b, LL m){
 6     LL ans= 1;
 7     a%= m;
 8     while(b){
 9         if(b&1)      ans= ans*a%m;
10         a= a*a%m;
11         b>>=1;
12     }
13     return ans;
14 }
15
16 int main(){
17     LL n;
18     scanf("%I64d",&n);
19     if(!n)    puts("1");
20     else    printf("%I64d\n",(1+quick_mod(2,n,mod))*quick_mod(2,n-1,mod)%mod);
21     return 0;
22 }

  后来我把输入改成 while(~scanf(....)) 来试了下,也过了,可以看出cf上是单组数据读入的,即便这样用while也行,注意添加好文件结束符EOF即可。

  水过后,我看着1000000007这个数值觉得用long long来处理好像也是有点浪费了,相乘是会溢出,但相加绝对不会溢出,只是已经很接近 int的上限而已。于是,我装了下B,把快速幂中的相乘改为了相加(同样利用快速幂的原理,二进制处理连续的加),这样,就能避开了long long(虽说节省不了什么资源,但可以训练下处理数据溢出的一些能力。不过在比赛中还是绝对不要这样给自己找麻烦,保险才是最重要的),写好快速乘取模后,却忘了在最后的 (1+2n)*2n-1 这里还有一个乘法,所以也调试了一点点时间。

 1 #include<cstdio>
 2 typedef long long LL;
 3 const int mod= 1000000007;
 4
 5 int quick_mul(int a, int b, int m){
 6     int ans= 0;
 7     a%= m;
 8     while(b){
 9         if(b&1)      ans= (ans+a)%m;
10         a= (a+a)%m;
11         b>>=1;
12     }
13     return ans;
14 }
15
16 int quick_mod(int a, LL b, int m){
17     int ans= 1;
18     a%= m;
19     while(b){
20         if(b&1)      ans= quick_mul(ans,a,m);
21         a= quick_mul(a,a,m);
22         b>>=1;
23     }
24     return ans;
25 }
26
27 int main(){
28     LL n;
29     while(~scanf("%I64d",&n)){
30         if(!n)    puts("1");
31         else {
32             int tmp1= quick_mod(2,n-1,mod);
33             int tmp2= tmp1*2%mod;
34             printf("%d\n",quick_mul((1+tmp2),tmp1,mod));
35         }
36     }
37     return 0;
38 }

  至此,装逼完成,成功水过。

时间: 2024-10-08 22:10:37

CodeForces 185A 快速幂的相关文章

CodeForces 185A. Plant(矩阵快速幂)

题目链接:http://codeforces.com/problemset/problem/185/A Dwarfs have planted a very interesting plant, which is a triangle directed "upwards". This plant has an amusing feature. After one year a triangle plant directed "upwards" divides int

CodeForces 185A Plant 矩阵快速幂

题意:最开始给你一个正三角形,每一步,一个正三角形可以变成三个正三角形和一个反三角形,而一个反三角形可以构成一个正三角形和三个反三角形,问额你n步之后一共有多少个正三角形. 解题思路:因为n太大,有10^18这么大,所以我们只能用矩阵快速幂来求. 中间矩阵为 3 1 1 3 初始矩阵为 0 (负) 1 (正) 解题代码: 1 // File Name: temp.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月17日 星期三 11时35

codeforces 185a(矩阵快速幂)

题意:三角形变化过程如下图 问正着的三角形的个数,n=1时1个,n=2时3个,n=3时10 - . 题解:可以找到规律 正x 倒y 1 0 3 1 10 6 - - 3*x+y 3*y+x 然后构造矩阵用矩阵快速幂求解. #include <cstdio> #include <iostream> #include <cstring> using namespace std; const int MOD = 1000000007; const int N = 3; str

Codeforces - 185A 简单矩阵快速幂

题意:求第n个三角形内部的上三角形个数 对每个三角形分别维护上下三角形个数,记为\(dp[1][i],dp[2][i]\) 规律很明显是 \(dp[1][i+1]=3*dp[1][i]+dp[2][i]\) \(dp[2][i+1]=3*dp[2][i]+dp[1][i]\) 别忘了快速幂里也要long long,白送了个TLE /*H E A D*/ inline ll mod(ll a){return a%MOD;} struct Matrix{ ll mt[5][5],r,c; void

【矩阵快速幂 】Codeforces 450B - Jzzhu and Sequences (公式转化)

[题目链接]click here~~ [题目大意] Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn modulo1000000007(109?+?7). [解题思路] /*A - Jzzhu and Sequences Codeforces 450B - Jzzhu and Sequences ( 矩阵快速幂 )

Codeforces Round #257 (Div. 2) B. Jzzhu and Sequences (矩阵快速幂)

题目链接:http://codeforces.com/problemset/problem/450/B 题意很好懂,矩阵快速幂模版题. 1 /* 2 | 1, -1 | | fn | 3 | 1, 0 | | fn-1 | 4 */ 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 using namespace std; 9 typedef __int64 LL; 10 LL mod =

CodeForces 450B (矩阵快速幂模板题+负数取模)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51919 题目大意:斐波那契数列推导.给定前f1,f2,推出指定第N项.注意负数取模的方式:-1%(10^9+7)=10^9+6. 解题思路: 首先解出快速幂矩阵.以f3为例. [f2]  * [1 -1] = [f2-f1]=[f3]  (幂1次) [f1]  * [1  0]     [f2]      [f2] 于是fn=[f2] *[1 -1]^(n-2)

codeforces 514E Darth Vader and Tree (dp+快速幂)

codeforces 514E Darth Vader and Tree (dp+快速幂) 题意: 有一棵树,每个节点有n个儿子,给出父亲到每个儿子的距离di,问离祖先距离不超过x的子孙有多少个(子孙包括祖先)对1e9+7取模. 限制: 1 <= n <= 1e5; 0 <= x <= 1e9; 1 <= di <= 100 思路: 因为di <= 100,所以可以用快速幂来处理这道题, 大概过程为:先用dp算出前100的答案,剩下的用快速幂来处理.

Xor-sequences CodeForces - 691E || 矩阵快速幂

Xor-sequences CodeForces - 691E 题意:在有n个数的数列中选k个数(可以重复选,可以不按顺序)形成一个数列,使得任意相邻两个数异或的结果转换成二进制后其中1的个数是三的倍数.求可能形成的不同数列个数(只要选出的数列中,任意两个元素在原序列中的位置不同,就算作不同的序列,比如在原数列[1,1]中选1个,那么第一个1和第二个1要分开算). 方法: 很容易列出dp方程: dp[k][i]表示取了k个,最后一个在第i位.a[i][j]表示i和j异或结果转换成二进制后1的个数