Tetrahedron(Codeforces Round #113 (Div. 2) + 打表找规律 + dp计数)

题目链接:

  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("*********\n")
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\n", 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("*********\n")
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\n", 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\n",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\n",linear_seq::gao(VI{0,3,6,21,60,183,546,1641,4920,14763},n-1));
102 }

三份代码跑的时间如下(忽略MLE那发,从上到下分别为BM,DP,公式):

 

posted @ 2019-02-27 21:51  Dillonh  阅读(298)  评论(0编辑  收藏  举报