Codeforces-161-E(快速幂,公式)

Codeforces 161E-Tetrahedron

本篇文章部分参考于

[https://blog.csdn.net/nolanddream/article/details/44086021]

题目原址

[http://codeforces.com/contest/166/problem/E]

题意

一个正四面体顶点为A,B,C,D,从D出发,每走一步,更变当前所在顶点(不能保持不变),给定一个数 n ,求能有几种不同路径使得第 n 步走到 D。

题解

  • 方法一(递推) O ( n ) O(n) O(n)
    分两种情况:1.第 n-2 步不在 D, 2.第 n-2 步在 D
    a[n] 是第 n 步到达 D 的不同路径数。
    · 对于 1 情况:第 n-2 步在A,B,C当中的一点,那么这时,在第 n-1 步能够到达 D,但其实他可以选择在第 n-1 到达另外两点,然后在第 n 步到达D,所以这种情况有 2a[n-1] 种。
    · 对于 2 情况:第 n-2 步在D点,那么他可以通过走到A,B,C中的任意一点,再回到D点,所以这种情况有 3a[n-2] 种。
    · 故有 a[n]=2a[n-1]+3a[n-2]
  • 方法二(公式)( O ( l o g 2 n ) O(log_{2}{n}) O(log2n))
    有上述公式,就能用特征方程解出 a[n] 表达式,对于任意的: A n = p A n − 1 + q A n − 2 A_{n}=pA_{n-1}+qA_{n-2} An=pAn1+qAn2有特征方程可写成: x 2 = p x + q x^{2}=px+q x2=px+q若其有解 x 1 , x 2 x_{1},x_{2} x1x2,则有: A n = a x 1 n − 1 + b x 2 n − 1 A_{n}=ax_{1}^{n-1}+bx_{2}^{n-1} An=ax1n1+bx2n1于是我们可以根据方法一中的表达式得出: a n = 3 4 ( 3 n − 1 − ( − 1 ) n − 1 )    ( n > 1 ) a_{n}=\frac{3}{4}(3^{n-1}-(-1)^{n-1})~~(n>1) an=43(3n1(1)n1)  (n>1)于是再运用快速幂来求 3 n − 1 3^{n-1} 3n1即可。还要寻找 4 的逆元,否则无法边运算边取模,很容易发现 m o d + 1 4 \frac{mod+1}{4} 4mod+14mod 中的逆元。(因为 mod = 1e9+7)
  • 方法三(动态规划) O ( n ) O(n) O(n)
    dp[i][j] 表示第 i 步走到 j 点,则有: d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ k ]    ( j ≠ k ) dp[i][j]=dp[i][j]+dp[i-1][k]~~(j\ne{k}) dp[i][j]=dp[i][j]+dp[i1][k]  (j̸=k)于是从遍历i,j,k,最后取 dp[n][3] 即可
  • 方法四(概率)
    n 步的总共不同路径有 3 n 3^{n} 3n条,若算出第 n 点到达 D 的概率,最后乘上 3 n 3^{n} 3n再取模即可。· 设 P n ( A ) P_{n}(A) Pn(A)为第 n 步到达 A 点的概率,那么由对称性可知: P n ( A ) + P n ( B ) + P n ( C ) + P n ( D ) = 1 P_{n}(A)+P_{n}(B)+P_{n}(C)+P_{n}(D)=1 Pn(A)+Pn(B)+Pn(C)+Pn(D)=1又知A,B,C三点完全等价,故有 P n ( A ) = P n ( B ) = P n ( C ) = 1 − P n ( D ) 3 P_{n}(A)=P_{n}(B)=P_{n}(C)=\frac{1-P_{n}(D)}{3} Pn(A)=Pn(B)=Pn(C)=31Pn(D)然后又可知第 n-1 步必定在A,B,C当中一点,且无论在哪一点总有 1 3 \frac{1}{3} 31的概率走到D,故有: P n + 1 ( D ) = 1 3 ( P n ( A ) + P n ( B ) + P n ( C ) ) = 1 − P n ( D ) 3 P_{n+1}(D)=\frac{1}{3}(P_{n}(A)+P_{n}(B)+P_{n}(C))=\frac{1-P_{n}(D)}{3} Pn+1(D)=31(Pn(A)+Pn(B)+Pn(C))=31Pn(D)结合 P 1 ( D ) = 0 P_{1}(D)=0 P1(D)=0可算出 P n ( D ) P_{n}(D) Pn(D)的表达式为: 3 n P n ( D ) = 3 4 ( 3 n − 1 − ( − 1 ) n − 1 ) 3^{n}P_{n}(D)=\frac{3}{4}(3^{n-1}-(-1)^{n-1}) 3nPn(D)=43(3n1(1)n1)

实现1(递推)

#include <stdio.h>
const int mod = (int)1e9 + 7;
const int maxn = (int)1e7 + 5;
long long a[maxn] = {0,0,3};//a[1]=0,a[2]=3
int main() {
    int n;
    scanf("%d", &n);
    int i;
    for (i = 3; i <= n; i++)
        a[i] = (2 * a[i - 1] + 3 * a[i - 2])%mod;
    printf("%I64d\n", a[n]);
}

实现1`(递推,优化空间)

#include <stdio.h>
const int mod = (int)1e9 + 7;
const int maxn = (int)1e7 + 5;
int main() {
    int n;
    scanf("%d", &n);
    int i;
    long long a=1,b=0,c=0;//a[0]=1,a[1]=0
    for (i = 2; i <= n; i++){        
        c = (2 * b + 3 * a)%mod;//计算a[n]  
        a=b;//更新a[n-2]
        b=c;//更新a[n-1]
    }
    printf("%I64d\n", c);
}

实现2(公式,快速幂)

#include <stdio.h>
const int mod = (int)1e9 + 7;
const int inv4 = (mod + 1) / 4;//4的逆元
    long long qpow(long long c, int n) {//快速幂
    long long ans=1;
    while (n > 0) {
        if (n & 1)            
        ans =ans*c%mod;        
        c=c*c%mod;        
        n >>= 1;
    }
    return ans;
}
int solve(int n) {
    long long ans;
    if (n & 1)        
        ans = (3 * (qpow(3, n - 1) - 1))%mod * inv4 %mod;
    else        
        ans = (3 * (qpow(3, n - 1) + 1))%mod * inv4 %mod;
    return (int)ans;
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%d\n", solve(n));
}

实现3(动态规划)

#include <stdio.h> 
const int mod = (int)1e9 + 7; 
int d[(int)1e7+5][4];//0=A,1=B,2=C,3=D 
int main() {     
    int n;     
    scanf("%d", &n);     
    d[1][0] = d[1][1] = d[1][2] = 1;    
    for (int i = 1; i <= n; i++)        
        for (int j = 0; j < 4; j++)            
            for (int k = 0; k < 4; k++)                
                if (j != k)//不能不动
                    d[i][j] = (d[i][j] + d[i - 1][k]) % mod;    
    printf("%d", d[n][3]);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值