hdu 4812 D Tree

本文介绍了一个树形DP算法,用于解决在给定树结构中寻找一条链,使得链上所有整数的乘积等于特定值K的问题。通过前缀和技巧和逆元概念,文章详细阐述了算法实现细节,包括输入输出格式、样例解析及核心代码。

http://www.elijahqi.win/archives/3336
Problem Description
There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each branch can be treated as a vertex). Today the students under the tree are considering a problem: Can we find such a chain on the tree so that the multiplication of all integers on the chain (mod 106 + 3) equals to K?
Can you help them in solving this problem?

Input
There are several test cases, please process till EOF.
Each test case starts with a line containing two integers N(1 <= N <= 105) and K(0 <=K < 106 + 3). The following line contains n numbers vi(1 <= vi < 106 + 3), where vi indicates the integer on vertex i. Then follows N - 1 lines. Each line contains two integers x and y, representing an undirected edge between vertex x and vertex y.

Output
For each test case, print a single line containing two integers a and b (where a < b), representing the two endpoints of the chain. If multiply solutions exist, please print the lexicographically smallest one. In case no solution exists, print “No solution”(without quotes) instead.
For more information, please refer to the Sample Output below.

Sample Input
5 60 2 5 2 3 3 1 2 1 3 2 4 2 5 5 2 2 5 2 3 3 1 2 1 3 2 4 2 5

Sample Output
3 4 No solution

Hint
1. “please print the lexicographically smallest one.”是指: 先按照第一个数字的大小进行比较,若第一个数字大小相同,则按照第二个数字大小进行比较,依次类推。 2. 若出现栈溢出,推荐使用C++语言提交,并通过以下方式扩栈: #pragma comment(linker,”/STACK:102400000,102400000”)

Source
2013ACM/ICPC亚洲区南京站现场赛——题目重现
我真是zz 这水题调了一天..
考虑做一个链的前缀和 然后每次都存下来 记录下标为这个乘积的逆元的情况的最小节点 然后每次先做后插入 最后再清空即可

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int mod=1e6+3;
const int N1=1100000;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
bool visit[N];int h[N],dis[N],inv[N1],ans1,ans2,v[N],sum,f[N],n,k,num,root,size[N],tmp[mod],K;
struct node{
    int y,next;
}data[N<<1];
inline void get_root(int x,int fa){
    size[x]=1;f[x]=0;
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if (y==fa||visit[y]) continue;
        get_root(y,x);size[x]+=size[y];f[x]=max(f[x],size[y]);
    }f[x]=max(sum-size[x],f[x]);
    if(f[x]<f[root]) root=x;
}
inline void get(int x,int y){
    if (x>y) swap(x,y);
    if (ans1>x) ans1=x,ans2=y;
    else if (ans1==x&&ans2>y) ans1=x,ans2=y;
}
inline void dfs(int x,int fa){
    if(tmp[dis[x]]!=inf) get(x,tmp[dis[x]]);
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if(y==fa||visit[y]) continue;
        dis[y]=(ll)dis[x]*v[y]%mod;dfs(y,x);
    }
}
inline void insert1(int x,int fa){
    tmp[(ll)inv[dis[x]]*K%mod]=min(tmp[(ll)inv[dis[x]]*K%mod],x);
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if (y==fa||visit[y]) continue;insert1(y,x);
    }
}
inline void clear(int x,int fa){
    tmp[(ll)inv[dis[x]]*K%mod]=inf;
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if(y==fa||visit[y]) continue;clear(y,x);
    }
}
inline void solve(int x){
    visit[x]=1;K=(ll)k*inv[v[x]]%mod;tmp[K]=x;
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if (visit[y]) continue;
        if (size[y]>size[x]) size[y]=sum-size[x];
        dis[y]=v[y];dfs(y,x);insert1(y,x);
    }tmp[K]=inf;
    for (int i=h[x];i;i=data[i].next){int y=data[i].y;if (visit[y]) continue;clear(y,x);}
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if (visit[y]) continue;
        sum=size[y];root=0;get_root(y,x);solve(root);
    }
}
int main(){
    freopen("hdu4812.in","r",stdin);
    inv[0]=inv[1]=1;memset(tmp,0x3f,sizeof(tmp));
    for (int i=2;i<=1e6+2;++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
    while(~scanf("%d%d",&n,&k)){
        for (int i=1;i<=n;++i) v[i]=read()%mod;
        memset(h,0,sizeof(h));num=0;memset(visit,0,sizeof(visit));ans1=ans2=inf;
        for (int i=1;i<n;++i){
            int x=read(),y=read();
            data[++num].y=y;data[num].next=h[x];h[x]=num;
            data[++num].y=x;data[num].next=h[y];h[y]=num;
        }root=0;f[0]=inf;sum=n;get_root(1,0);
        solve(root);
        if (ans1==inf&&ans2==inf) puts("No solution");
        else printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

【SCI一区复现】基于配电网韧性提升的应急移动电源预配置和动态调度(下)—MPS动态调度(Matlab代码实现)内容概要:本文档围绕“基于配电网韧性提升的应急移动电源预配置和动态调度”主题,重点介绍MPS(Mobile Power Sources)动态调度的Matlab代码实现,是SCI一区论文复现的技术资料。内容涵盖在灾害或故障等极端场景下,如何通过优化算法对应急移动电源进行科学调度,以提升配电网在突发事件中的恢复能力与供电可靠性。文档强调采用先进的智能优化算法进行建模求解,并结合IEEE标准测试系统(如IEEE33节点)进行仿真验证,具有较强的学术前沿性和工程应用价值。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电力系统优化、配电网韧性、应急电源调度等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于复现高水平期刊(SCI一区、IEEE顶刊)中关于配电网韧性与移动电源调度的研究成果;②支撑科研项目中的模型构建与算法开发,提升配电网在故障后的快速恢复能力;③为电力系统应急调度策略提供仿真工具与技术参考。; 阅读建议:建议结合前篇“MPS预配置”内容系统学习,重点关注动态调度模型的数学建模、目标函数设计与Matlab代码实现细节,建议配合YALMIP等优化工具包进行仿真实验,并参考文中提供的网盘资源获取完整代码与数据。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值