cug 1436 A Strange Dream

1436: A strange dream

Time Limit: 5 Sec   Memory Limit: 128 MB
Submit: 17   Solved: 2
[ Submit][ Status][ Web Board]

Description

One day, Leo has a strange dream. In this dream, there are n scenes (marked from 1 to n). Each scene has a number pi. If Leo has x money at hand, when Leo enters the ith scene, his money will become least_common_multiple(x,pi). Notice that Leo will become mad if he goes to another scene but his money remain unchanged.
Suppose Leo is staying in the first scene (with p1 money). Please find out how many paths which can arrive at the nth scene and has k money there. Of course, you can't make Leo mad.
Two paths are regarded to be different if and only if the edge sequences are different. And we guarantee no repeated edge.

Input

There are multiple test cases. For each test case:
The first line contains three integer n (2 ≤ n ≤ 5000), m (2 ≤ m ≤ 20000) and k (2 ≤ k ≤ 10^6), as described above. Then followed by m lines. Each line contains two integer u, v (1 ≤ u, v ≤ n, u ≠ v), indicating that we can go to vth scene from uth scene directly. The last line of each case contains n integer pi (1 ≤ pi ≤ 10^6).
Process to the end of file. 

Output

One line for each case, output the number of paths mod 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

显然路径上的每一个点的钱都应该是K的约数,每个点的p也应该是K的约数
10^6以内的一个i,最多有240个约数
所以等于每个点最多240个状态.
用spfa可以求出对于所有点哪些状态是可达的
紧接着就可以用记忆化搜索求出路径数.
一开始在spfa里直接求路径数,这样只要某个点的某个状态的路径数改变了,这个点就要入队,无限TLE呀.....
但其实上每个点的每个状态最多只需进队一次的..


#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;

#define N 5005
#define M 250
#define MM 20005
#define mod 1000000007

inline int input(){
    int ret=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
    return ret;
}

int n,m,k,cnt;
int a[MM],b[MM],p[N],pp[M],fac[1000000+2],mut[M][M];
int dp[N][M];
bool val[N][M],inq[N];

struct EDGE{
    int v,next;
}edge[MM],rev[MM];
int head[MM],head1[MM],e,ee;
inline void add(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;

    rev[ee].v=u;
    rev[ee].next=head1[v];
    head1[v]=ee++;
}

inline int lcm(int a,int b){
    int x=a,y=b,t;
    while(y){
        t=x;
        x=y;
        y=t%x;
    }
    return a/x*b;
}

inline void Fun(int k){
    memset(fac,-1,sizeof(fac));
    cnt=0;
    for(int i=1;i*i<=k;i++){
        if(k%i==0){
            pp[cnt]=i,fac[i]=cnt,cnt++;
            if(k/i!=i){
                pp[cnt]=k/i,fac[k/i]=cnt,cnt++;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        for(int j=i;j<cnt;j++){
            mut[i][j]=mut[j][i]=lcm(pp[i],pp[j]);
        }
    }
}

inline void spfa(){
    queue<int>q;
    memset(inq,0,sizeof(inq));
    memset(val,0,sizeof(val));
    q.push(1);
    val[1][fac[p[1]]]=1;

    inq[1]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        inq[x]=0;
        for(int j=0;j<cnt;j++){
            if(!val[x][j]) continue;
            if(j==k) continue;
            for(int i=head[x];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(pp[j] % p[v]==0) continue;
                int vv=mut[j][fac[p[v]]];
                if(k%vv!=0) continue;
                if(val[v][fac[vv]]==1) continue;
                val[v][fac[vv]]=1;
                if(!inq[v]){
                    inq[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

inline int dfs(int x,int y){
    if(dp[x][fac[y]]!=-1) return dp[x][fac[y]];
    int ans=0;
    for(int i=head1[x];i!=-1;i=rev[i].next){
        int v=rev[i].v;
        for(int j=0;j<cnt;j++){
            if(pp[j]%p[x]==0) continue;
            if(!val[v][j]) continue;
            if(mut[j][fac[p[x]]] == y){
                ans += dfs(v,pp[j]);
                ans%=mod;
            }
        }
    }
    return dp[x][fac[y]]=ans%mod;
}

int main(){
    while(scanf("%d",&n)!=EOF){
        m=input(),k=input();
        Fun(k);

        for(int i=0;i<m;i++){
            a[i]=input(),b[i]=input();
        }
        for(int i=1;i<=n;i++){
            p[i]=input();
        }
        if(fac[p[1]]==-1 || fac[p[n]]==-1){
            puts("0");
        }
        else{
            memset(head,-1,sizeof(head));
            memset(head1,-1,sizeof(head1));
            e=ee=0;
            for(int i=0;i<m;i++){
                if(fac[p[a[i]]]==-1) continue;
                if(fac[p[b[i]]]==-1) continue;
                add(a[i],b[i]);
            }
            spfa();
            memset(dp,-1,sizeof(dp));
            memset(dp[1],0,sizeof(dp[1]));
            dp[1][fac[p[1]]]=1;
            printf("%d\n",dfs(n,k));
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信安综合实践是指信号安全综合实践课程,是中国地质大学(CUG)信号与信息处理专业的一门重要课程。此课程旨在通过理论与实践相结合的方式,培养学生的信息安全意识和实践能力。 信安综合实践主要涵盖以下几个方面。首先,课程通过介绍信息安全的基本知识以及网络威胁的类型和特点,提醒学生关注和重视信息安全问题。其次,课程通过实践项目,教导学生应对不同类型的网络攻击和安全漏洞的方法和技巧。学生将学习到如何使用各种安全工具和软件来保护计算机和网络系统的安全。同时,还会了解如何进行安全检测和防范措施的规划与实施。 信安综合实践还重视培养学生的团队合作和解决问题的能力。在项目实践中,学生需要组成小组,共同合作完成一些实际的安全任务,例如构建安全网络环境、开展网络安全漏洞检测、编写网络安全策略等。通过与同学的合作交流,学生可以锻炼自己的团队合作和沟通能力。 信安综合实践的开设有益于提高学生的信息安全意识和实践能力,培养他们成为具备信息安全知识与技巧的专业人才。这些专业人才在未来的工作中,可以为各种组织和企业提供安全保护和风险评估服务,促进网络安全环境的建设与发展。 总之,信安综合实践课程是中国地质大学的一门重要课程,通过理论与实践相结合的方式,培养学生的信息安全意识和实践能力。这将为他们未来的工作提供坚实的基础,并为网络安全行业的发展做出贡献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值