• 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
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    删除文件夹右键下的部分目录
    c# datagridview导出到excel【转载】
    使用AO新增记录的3种方法【转载】
    AE 打包
    ArcMap 9使用技巧
    ArcEngine 渲染的使用【转载】
    关于数据库版本压缩
    SDE数据源直连
    ArcCatalog 9中的使用技巧
    AE指定字段转成注记
  • 原文地址:https://www.cnblogs.com/xuesu/p/4509014.html
Copyright © 2020-2023  润新知