ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷 P3758 [TJOI2017]可乐(DP||矩阵优化)

2020-08-31 23:03:24  阅读:296  来源: 互联网

标签:洛谷 Mat int 矩阵 P3758 TJOI2017 ans const include


题目链接:https://www.luogu.com.cn/problem/P3758

 

在不用矩阵优化之前,可以写递推/记忆化:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=35;
 6 const int maxn=1e6+5;
 7 const int mod=2017;
 8 int n,m,ans,t;
 9 int dp[N][maxn];
10 int head[N],tot;
11 struct node{
12     int to,next;
13 }edge[N<<1];
14 void add(int u,int v){
15     edge[tot].to=v;
16     edge[tot].next=head[u];
17     head[u]=tot++;
18 }
19 int DFS(int u,int t,int f){
20     if(dp[u][t]) return dp[u][t];
21     if(t==1) return 1;
22     dp[u][t]=1;
23     for(int i=head[u];i!=-1;i=edge[i].next){
24         int v=edge[i].to;
25         dp[u][t]+=DFS(v,t-1,u);
26         dp[u][t]%=mod;
27     }
28     dp[u][t]+=DFS(u,t-1,f);
29     dp[u][t]%=mod;
30     return dp[u][t];
31 }
32 int main(){
33     memset(head,-1,sizeof(head));
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=m;i++){
36         int u,v;
37         scanf("%d%d",&u,&v);
38         add(u,v);
39         add(v,u);
40     }
41     scanf("%d",&t);
42     printf("%d",DFS(1,t+1,0));
43     return 0;
44 }
AC代码

 

然而这道题可以用矩阵快速幂优化:

用邻接矩阵存图,那么这恰好就是一个矩阵A,矩阵的应用可以求有向图中从a到b经过k条边的可能数。

那么经过t次矩阵乘法,即$A^t$,然后$ans=\sum\limits_{i=0}^n a[1][i]$

(其中b为单元矩阵,即对角线为1,其余为0的矩阵,相当于普通的“1”。)

 

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 int n,m,t,sum;
 6 const int mod=2017;
 7 struct Mat{
 8     int mat[31][31];
 9     Mat(){
10         memset(mat,0,sizeof(mat));
11     }
12     Mat operator*(const Mat &self)const{
13         Mat ans;
14         for(int i=0;i<=30;i++)
15         for(int j=0;j<=30;j++)
16         for(int k=0;k<=30;k++)
17             (ans.mat[i][j]+=mat[i][k]*self.mat[k][j])%=mod;
18         return ans;
19     }
20 }a,b;
21 void init(){
22     for(int i=0;i<=30;i++) b.mat[i][i]=1;//b为单位矩阵 
23 }
24 void ksm(int n){
25     while(n){
26         if(n&1) b=b*a;
27         a=a*a;
28         n>>=1;
29     }
30 }
31 int main(){
32     scanf("%d%d",&n,&m);
33     for(int i=1;i<=m;i++){
34         int u,v;
35         scanf("%d%d",&u,&v);
36         a.mat[u][v]=a.mat[v][u]=1;
37     }
38     for(int i=0;i<=n;i++) { a.mat[i][0]=1; a.mat[i][i]=1;}
39     scanf("%d",&t);
40     init();
41     ksm(t);
42     for(int i=0;i<=n;i++) (sum+=b.mat[1][i])%=mod;
43     printf("%d\n",sum);
44     return 0;
45 }
AC代码

 

标签:洛谷,Mat,int,矩阵,P3758,TJOI2017,ans,const,include
来源: https://www.cnblogs.com/New-ljx/p/13592526.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有