题目大意:如图,给定n个点形成环,中间一个点0,每个点到0连一条边,问从0开始,经过m条边有多少条路径使得回到0点,每个点每条边都可以经过多次。
输出路径数
思路:这个题目如果不考虑数据规模的话,用矩阵乘法可以解这个题,详见矩阵的十种应用,那个适用于100个点的任意图。
这个题n<=1000,m<=5000 不可,所以我想到了一个dp方法,dp[i][j]表示i步到j的方案数,转移就好说了。时间复杂度似乎也是可以解决的。
这个题并没有把结果取余,哎,这样的话,答案就是个好几千位的数了。囧。。。时间复杂度还得算上两个数相加的时间!!!果断超内存超时。
然后我就想到了一个一维的dp。dp[i][0]表示i步到0的方案数,dp[i][1]表示i步到非0的方案数。
转移为:dp[i+1][0] += dp[i][1];
dp[i+1][1] += dp[i][0]*n + dp[i][1] * 2;
这样的话,题目就简单了。
我偷懒写的java。
code:
import java.util.*;
import java.math.*;
public class Solution
{
public static void main(String args[])
{
BigInteger dp[][]=new BigInteger[5010][2];
int n,m;
Scanner sc=new Scanner(System.in);
while(sc.hasNext())
{
n=sc.nextInt();
m=sc.nextInt();
for(int i=0;i<=m;i++)
for(int j=0;j<2;j++)
dp[i][j]=BigInteger.ZERO;
dp[0][0]=BigInteger.ONE;
for(int i = 0;i < m;i++)
{
dp[i+1][0]=dp[i+1][0].add( dp[i][1]) ;
BigInteger t=new BigInteger(Integer.toString(n));
t=t.multiply(dp[i][0]);
dp[i+1][1]=dp[i+1][1].add(t) ;
dp[i+1][1]=dp[i+1][1].add(dp[i][1]) ;
dp[i+1][1]=dp[i+1][1].add(dp[i][1]) ;
}
System.out.println(dp[m][0]);
}
}
}