尼玛。。  一个 long  long  调了 两天 。。

解题:

我们 可以沿着某一条从1到n的路线走下去,看能否找到合适的答案。。

剪枝就是:

1: 走过的不在走  记忆话搜索。。

2:   如果某一点不是k的约数或者大于k或者和前面相等,不在往下走。。

注意:因为k的约数的范围可能特别大,数组放不下,所以用map哈希。。

用vector建立邻接表。。

View Code
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<cmath>
#define mod 1000000007
using namespace std;
typedef long long ll;
const int maxn=2005;
map<ll,int>node;
int n,m;
int k;
ll dp[maxn][maxn];//就是这个ll 
ll mm[maxn];
vector<int>gg[maxn];
int pos;
void hash(int d)
{
    int  p=(int)sqrt(1.0*d);
    pos=1;
    for(int i=1;i<p;i++)
    if(d%i==0)
        node[i]=pos++,node[d/i]=pos++;
    if(d%p==0)node[p]=pos;
}
ll gcd(ll a,ll b)
{
    if(a<b)
        a=a+b,b=a-b,a=a-b;
    while(b)
    {
        ll temp=a;
        a=b;
        b=temp%b;
    }
    return a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
ll dfs(int u,ll x)
{

   
    if(dp[u][node[x]])
        return dp[u][node[x]];
    if(u==n)
        return x==k;
   
    for(int i=0;i<gg[u].size();i++)
    {
        if(k%mm[gg[u][i]])continue;
        ll temp=lcm(x,mm[gg[u][i]]);
        if(node[temp]!=0&&temp!=x&&temp<=k)
        //if(temp==x||temp>k)continue;
          dp[u][node[x]]+=dfs(gg[u][i],temp)%mod;
    }
    return dp[u][node[x]]%mod;
}
int main()
{
     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
       // cout<<n<<" "<<m<<" "<<k<<endl;
       node.clear();
       for(int i=0;i<=n;i++)
       gg[i].clear();
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            gg[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
            scanf("%lld",&mm[i]);
        hash(k);

        memset(dp,0,sizeof(dp));
        ll ans=dfs(1,mm[1]);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted on 2012-10-04 10:56  一把刷子  阅读(248)  评论(0编辑  收藏  举报