ZOJ 3644 Kitty's Game dfs,记忆化搜索,map映射 难度:2

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834

从点1出发,假设现在在i,点数为sta,则下一步的点数必然不能是sta的因数,所以不会形成环,只需从1直接走,走到n即可.

但是如果这样的话时空复杂度就都是nk,明显不满足题意,而这个时候我们可以想到,每个状态都必然是k的约数,(点数不是k的约数的节点不在路上,可以无视),而约数的个数也就k^0.5个,可以直接用map映射,这样时空复杂度都是n*k^0.5,可以解出答案.

一开始直接用dfs,结果TLE了.

#include <cstdio>

#include <cstring>

#include <map>

using namespace std;

const int maxn = 2001;

const int maxm = 2e4+4;

const int mod = 1000000007;

const int maxk = 1e6+6;

int n,m,k;

int p[maxn];

typedef long long ll;

map<int ,int >id;

ll dp[maxn][maxn];

int first[maxn];

struct edge{

    int nxt,t;

}e[maxm];

void addedge(int f,int t,int ind){

    e[ind].nxt = first[f];

    e[ind].t = t;

    first[f] = ind;

}

int bit[30],num;

void apart(int k){

    for(int i=2;i*i<=k;i++){

        while(k%i==0){

            bit[num++]=i;

            k/=i;

        }

    }

    if(k>1)bit[num++]=k;

}

ll gcd(ll a,ll b){

    if(b==0)return a;

    return gcd(b,a%b);

}

ll lcm(ll a,ll b){

    return a*b/gcd(a,b);

}

bool vis[maxn];

int cnt;

ll dfs(int s,int sav){

    if(id[sav]!=0&&dp[s][id[sav]]!=0)return dp[s][id[sav]];

    if(s==n)return sav==k?1:0;

    vis[s]=true;

    if(id[sav]==0)id[sav]=++cnt;

    for(int pe=first[s];pe!=-1;pe=e[pe].nxt){

        int t=e[pe].t;

        ll lcmnum=lcm(p[t],sav);

        if(vis[t]||lcmnum==sav||lcmnum>k)continue;

        dp[s][id[sav]]+=dfs(t,lcmnum);

        dp[s][id[sav]]%=mod;

    }

    vis[s]=false;

    return dp[s][id[sav]];

}

int solve(){

    num=0;

    apart(k);

    if(lcm(p[1],k)!=k||lcm(p[n],k)!=k)return 0;

    for(int i=2;i<n;i++){

        if(lcm(p[i],k)!=k){

            vis[i]=true;

        }

    }

    return dfs(1,p[1]);

}



void init(){

    memset(first,-1,sizeof first);

    memset(dp,0,sizeof dp);

    memset(vis,0,sizeof vis);

    cnt=0;

    id.clear();

}

int main(){

    while(scanf("%d%d%d",&n,&m,&k)==3){

        init();

        for(int i = 0;i < m;i++){

            int f,t;

            scanf("%d%d",&f,&t);

            addedge(f,t,i);

        }

        for(int i = 1;i <= n;i++){

            scanf("%d",p+i);

        }

        int ans=solve();

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(game)