Description
Kitty is a little cat. She is crazy about a game recently.
There are n scenes in the game(mark from 1 to n). Each scene has a number pi. Kitty's score will become least_common_multiple(x,pi) when Kitty enter the ith scene. x is the score that Kitty had previous. Notice that Kitty will become mad If she go to another scene but the score didn't change.
Kitty is staying in the first scene now(with p1 score). Please find out how many paths which can arrive at the nth scene and has k scores at there. Of course, you can't make Kitty mad.
We regard two paths different if and only if the edge sequence is different.
Input
There are multiple test cases. For each test case:
The first line contains three integer n(2 ≤ n ≤ 2000), m(2 ≤ m ≤ 20000), k(2 ≤ k ≤ 106). Then followed by m lines. Each line contains two integer u, v(1 ≤ u, v ≤ n, u ≠ v) indicate we can go to vth scene from uth scene directly. The last line of each case contains n integer pi(1 ≤pi ≤ 106).
Process to the end of input.
Output
One line for each case. The number of paths module 1000000007.
Sample Input
5 6 84 1 2 2 5 1 3 3 5 1 4 4 5 1 5 4 12 21
Sample Output
2
思路:很容易想到一个dp方程 dp [u] [now_val] = sigma(dp [v] [ lcm(now_val,num[v])] ) 表示从u节点,当前为now_val值出发,到n节点,为k值有多少种方案。 其中v是u以有向边相连的一个节点,lcm是最小公倍数。
代码:
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#define LL long long
using namespace std;
const long mod=1000000007;
const long M=2100;
long n,m,k,num[M];
map<int,int> dp[M];
long head[M],to[M*M],Next[M*M],cnt;
void init_edge(){
memset(head,-1,sizeof(head));
for (long i=1;i<=n;++i) dp[i].clear();
cnt=0;
}
void add_edge(long u,long v){
Next[cnt]=head[u]; to[cnt]=v; head[u]=cnt++;
}
long gcd(long x,long y){
while (y){
long temp=y;
y=x%y; x=temp;
}
return x;
}
LL lcm(long x,long y){
return (LL)x*y/gcd(x,y);
}
long dfs(long u,long now){
if (dp[u].find(now)!=dp[u].end()) return dp[u][now];
dp[u][now]=0;
for (long i=head[u];i!=-1;i=Next[i]){
long v=to[i];
LL LCM;
if ((LCM=lcm(num[v],now))==now || LCM>k) continue;
dp[u][now]=(dp[u][now]+dfs(v,LCM))%mod;
}
return dp[u][now];
}
int main(){
while (~scanf("%d%d%d",&n,&m,&k)){
init_edge();
for (long i=1;i<=m;++i){
long u,v; scanf("%d%d",&u,&v);
add_edge(u,v);
}
for (long i=1;i<=n;++i) scanf("%d",&num[i]);
dp[n][k]=1;
printf("%d\n",dfs(1,num[1]));
}
return 0;
}