题目链接:
https://codeforces.com/contest/166/problem/E
题目:
题意:
给你一个三菱锥,初始时你在D点,然后你每次可以往相邻的顶点移动,问你第n步回到D点的方案数。
思路:
打表找规律得到的序列是0,3,6,21,60,183,546,1641,4920,14763,通过肉眼看或者oeis可以得到规律为。
dp计数:dp[i][j]表示在第i步时站在位置j的方案数,j的取值为[0,3],分别表示D,A,B,C点,转移方程肯定是从其他三个点转移。
代码实现如下:
非dp计数:
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("********* ") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 1e7 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n; 42 LL dp[maxn]; 43 44 int qpow(int x, int n) { 45 int res = 1; 46 while(n) { 47 if(n & 1) res = 1LL * res * x % mod; 48 x = 1LL * x * x % mod; 49 n >>= 1; 50 } 51 return res; 52 } 53 54 int main(){ 55 int inv = qpow(4, mod - 2); 56 LL cnt = 1; 57 scanf("%d", &n); 58 for(int i = 1; i <= n; i++) { 59 cnt = cnt * 3 % mod; 60 if(i & 1) dp[i] = (cnt - 3 + mod) % mod * inv % mod; 61 else dp[i] = (cnt + 3) % mod * inv % mod; 62 } 63 printf("%lld ", dp[n]); 64 return 0; 65 }
dp计数代码:
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("********* ") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 1e7 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n; 42 int dp[maxn][4]; 43 44 int main(){ 45 scanf("%d", &n); 46 dp[0][0] = 1; 47 for(int i = 1; i <= n; i++) { 48 for(int j = 0; j < 4; j++) { 49 for(int k = 0; k < 4; k++) { 50 if(j == k) continue; 51 dp[i][j] = (1LL * dp[i][j] + dp[i-1][k]) % mod; 52 } 53 } 54 } 55 printf("%d ", dp[n][0]); 56 return 0; 57 }
BM代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <map> 8 #include <set> 9 #include <cassert> 10 using namespace std; 11 #define rep(i,a,n) for (int i=a;i<n;i++) 12 #define per(i,a,n) for (int i=n-1;i>=a;i--) 13 #define pb push_back 14 #define mp make_pair 15 #define all(x) (x).begin(),(x).end() 16 #define fi first 17 #define se second 18 #define SZ(x) ((int)(x).size()) 19 typedef vector<int> VI; 20 typedef long long ll; 21 typedef pair<int,int> PII; 22 const ll mod=1000000007; 23 ll powmod(ll a,ll b) { 24 ll res=1; 25 a%=mod; 26 assert(b>=0); 27 for(; b; b>>=1) { 28 if(b&1)res=res*a%mod; 29 a=a*a%mod; 30 } 31 return res; 32 } 33 // head 34 int _,n; 35 namespace linear_seq { 36 const int N=100100; 37 ll res[N],base[N],_c[N],_md[N]; 38 vector<int> Md; 39 void mul(ll *a,ll *b,int k) { 40 rep(i,0,k+k) _c[i]=0; 41 rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod; 42 for (int i=k+k-1; i>=k; i--) if (_c[i]) 43 rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod; 44 rep(i,0,k) a[i]=_c[i]; 45 } 46 int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+... 47 // printf("%d ",SZ(b)); 48 ll ans=0,pnt=0; 49 int k=SZ(a); 50 assert(SZ(a)==SZ(b)); 51 rep(i,0,k) _md[k-1-i]=-a[i]; 52 _md[k]=1; 53 Md.clear(); 54 rep(i,0,k) if (_md[i]!=0) Md.push_back(i); 55 rep(i,0,k) res[i]=base[i]=0; 56 res[0]=1; 57 while ((1ll<<pnt)<=n) pnt++; 58 for (int p=pnt; p>=0; p--) { 59 mul(res,res,k); 60 if ((n>>p)&1) { 61 for (int i=k-1; i>=0; i--) res[i+1]=res[i]; 62 res[0]=0; 63 rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod; 64 } 65 } 66 rep(i,0,k) ans=(ans+res[i]*b[i])%mod; 67 if (ans<0) ans+=mod; 68 return ans; 69 } 70 VI BM(VI s) { 71 VI C(1,1),B(1,1); 72 int L=0,m=1,b=1; 73 rep(n,0,SZ(s)) { 74 ll d=0; 75 rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod; 76 if (d==0) ++m; 77 else if (2*L<=n) { 78 VI T=C; 79 ll c=mod-d*powmod(b,mod-2)%mod; 80 while (SZ(C)<SZ(B)+m) C.pb(0); 81 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; 82 L=n+1-L,B=T,b=d,m=1; 83 } else { 84 ll c=mod-d*powmod(b,mod-2)%mod; 85 while (SZ(C)<SZ(B)+m) C.pb(0); 86 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; 87 ++m; 88 } 89 } 90 return C; 91 } 92 int gao(VI a,ll n) { 93 VI c=BM(a); 94 c.erase(c.begin()); 95 rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod; 96 return solve(n,c,VI(a.begin(),a.begin()+SZ(c))); 97 } 98 }; 99 int main() { 100 scanf("%d",&n); 101 printf("%d ",linear_seq::gao(VI{0,3,6,21,60,183,546,1641,4920,14763},n-1)); 102 }
三份代码跑的时间如下(忽略MLE那发,从上到下分别为BM,DP,公式):