zoj3644

題意大概是,,在一個圖中有n個點,,每個點有個值Pi,要你從一出發是的每次都到一個點,,然後你獲得改點的與之前你已經有的點的最小公倍數,,然後不能去已經是最小公倍數不改變的點,最後使得獲得的爲k問有多少種路徑,,錯了很多次。。。讓我很心痛這個題目是DP,,記憶化搜索,,但是其中的哈希法讓我很心痛啊,,,已經接觸了一些哈希讓我開始有了一定的瞭解,,,我相信我下次一定可以做的更好。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define mod 1000000007
#define ll long long

struct node {
int v;
int next;
}e[20005];
ll dp[2005][2005];
int head[20005*3];
int n,m,k;
int val[2005];
int cnt;
map<ll,int>s;
void  pre()
{
    s.clear();
    cnt=1;
    for(int i=1;i<=k/2;i++)
        if(k%i==0){
            s[i]=cnt++;
        }
     s[k]=cnt++;
}//哈希法,,,非常牛逼的算法,,我覺得這是輔助算法裏面超級牛逼的
int add(int x,int y,int index)
{
    e[index].v=y;
    e[index].next=head[x];
    head[x]=index++;
    return index;
}

int  gcd(int a,int b)
{
    if(a<b)
    {
    int temp=a;
        a=b;
        b=temp;
    }
    if(b==0)//沒想到在這裏在了跟頭,,,一直是wa,,,,我就說嘛,,,
        return a;
    else
        return gcd(b,a%b);
}

ll DFS(int fa,int lp)
{
    if(fa==n)  return lp==k;
    if(dp[fa][s[lp]]!=0) return dp[fa][s[lp]];
     for(int i=head[fa];i!=-1;i=e[i].next)
     {
         int t=e[i].v;
        if(k%val[t]!=0)continue;
         int mulit2=val[t]/gcd(lp,val[t])*lp;
        if(mulit2==lp)continue;
         if(s[lp]!=0&&mulit2<=k)
         dp[fa][s[lp]]=(dp[fa][s[lp]]%mod+DFS(t,mulit2)%mod)%mod;
     }
     return dp[fa][s[lp]];
}

int main()
{
   //freopen("in.txt","r",stdin);
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        int x,y;
      int   index=0;
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
         pre();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            index=add(x,y,index);
        }
        for(int i=1;i<=n;i++)
            {
                scanf("%d",&val[i]);
            }
       if(k%val[1]==0)
          printf("%lld\n",DFS(1,val[1])%mod);
        else
          printf("0\n");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章