[Galaxy OJ] Contest 501 解题报告

T1

其实就是某种程度上的树上最长链。

#include<bits/stdc++.h>
using namespace std;
constexpr int Size=1e6+1;
typedef long long lli;
struct edge{
    int v;
    lli w;
    int nxt;
    edge():v(0),w(0),nxt(0){}
    edge(int _v,lli _w,int _nxt):v(_v),w(_w),nxt(_nxt){}
}e[Size];
int n;
int head[Size];
lli ans;
lli cap[Size];
lli dfs(lli now,lli father);
void add_edge(int u,int v,lli w);
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",cap+i);
    for(int i=1,u,v;i<n;i++){
        lli w;
        scanf("%d%d%lld",&u,&v,&w);
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
    dfs(1,0);
    printf("%lld",ans);
    return 0;
}
lli dfs(lli now,lli father)
{
    lli sub(0),lth(0);
    for(int i=head[now];i!=0;i=e[i].nxt){
        if(e[i].v==father)
            continue;
        lli val=dfs(e[i].v,now)-e[i].w;
        if(val>sub) sub=val;
        if(sub>lth) swap(sub,lth);
    }
    lli res=lth+sub+cap[now];
    ans=max(ans,res);
    return lth+cap[now];
}
void add_edge(int u,int v,lli w)
{
    static int cnt;
    e[++cnt]={v,w,head[u]};
    head[u]=cnt;
}

CF1105C

f[i][j]=n代表数组的第i位在前i位的数字之和模3等于j时共有n种可能的取值,循环时引入k来状态转移即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long lli;
constexpr int Size=1e6+1,Mod=1e9+7;
int n,l,r;
lli f[Size][3];
inline lli add(lli &a,lli b){return a=(a+b)%Mod;}
int main()
{
    scanf("%d%d%d",&n,&l,&r);
    f[0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
                add(f[i][(j+k)%3],f[i-1][j]*((r-k+3)/3-(l-1-k+3)/3));
    printf("%lld",f[n][0]%Mod);
}

CF1070A

设三元组(d,s,n)代表能被d整除且各位数字之和为s的最小正整数是nfor(0->9)逐位枚举状态,则状态转移方程为:

\[ \left\{ \begin{align} d_i&=(d_{now}\times 10+i)\ \mathrm{mod}\ d\\ s_i&=s_{now}+i\\ n_i&=i \end{align} \right. \]

用广搜进行状态转移即可。

#include<bits/stdc++.h>
#define wrap make_pair
using namespace std;
typedef pair<int,int> pir;
struct node{
    int d,s,val;
    node():d(0),s(0),val(0){}
    node(int _d,int _s,int _v):d(_d),s(_s),val(_v){}
}ans[501][5001];
int d,s;
queue<pir> q;
bitset<5001> vis[501];
void bfs();
void print(int nd,int ns);
int main()
{
    scanf("%d%d",&d,&s);
    bfs();
    vis[0][s]?print(0,s):(void)printf("-1");
    return 0;
}
void bfs()
{
    vis[0][0]=true;
    q.push(wrap(0,0));
    while(!q.empty()){
        int nd,ns;
        tie(nd,ns)=q.front();
        q.pop();
        for(int i=0;i<=9;i++){
            int di=(nd*10+i)%d;
            int si=ns+i;
            if(vis[di][si]||si>s)
                continue;
            vis[di][si]=true;
            ans[di][si]={nd,ns,i};
            q.push(wrap(di,si));
        }
    }
}
void print(int nd,int ns)
{
    if(nd==0&&ns==0)
        return;
    print(ans[nd][ns].d,ans[nd][ns].s);
    putchar(ans[nd][ns].val+'0');
}

猜你喜欢

转载自www.cnblogs.com/Sepia/p/10299297.html
今日推荐