hgoi # 20190813

T1- cake

You have a size of \ (n × m \) cake, you want to cut it into \ (1 × 1 \) small pieces. Each time you can select sideways or vertically cut back, the cake into two parts, the two parts then were cut until all turned \ (1 × 1 \) small pieces. You want to know how many different kinds of cutting method (swap any two pieces of cake cutting sequence of the same calculation scheme), to \ (1000000007 \) modulo.

solution

A lot of practice, n and m size of only 300, can record search, it can also dp
dp thing to do is to cut all combinations considered answer two small contribution cake

ac Code

#include<bits/stdc++.h>
#define mod 1000000007 
#define ll long long
#define N 310
using namespace std;
ll n,m,dp[N][N];
void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
int main()
{
    freopen("cake.in","r",stdin),freopen("cake.out","w",stdout);
    scanf("%lld%lld",&n,&m),dp[1][1]=1;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    {
        for(int k=1;k<i;k++)add(dp[i][j],dp[i-k][j]*dp[k][j]%mod);
        for(int k=1;k<j;k++)add(dp[i][j],dp[i][j-k]*dp[i][k]%mod);
    }
    printf("%lld\n",dp[n][m]);
    return 0;
}

T2- give change

L L where small countries because there is no universal mobile payments, large-scale use is still in the bill. A total of \ (n \) denominations of banknotes in denominations different from each other. One day go to the store to buy a small L price \ (X \) yuan items, he knew in advance the number of banknotes of each denomination of their own hands and the hands of the clerk, he wanted to know how many pay a total of - way to find the money . Give change in different ways, if and only if there is a nominal value, the number of different bills of different bill in both the number of programs L pay small denominations or the clerk to find the denominations - Two pay. In addition, the total face value of paper money provided to pay for a small L \ (the Y-\) , the small L pay bills can not exist in the face value of less than or equal \ (YX \) banknotes (otherwise there would be no need to pay this note a).

solution

Consider the most basic dp, dp [i] [j ] represents all the banknotes taken into account i and i later, and for the number of programs of j
for the delivery of money \ (dp [i] [j ] = \ sum \ limits_ {k = 0} ^ {b [i]
} {dp [i + 1] [jk × a [i]]} (j <X + a [i]) \) to repay \ (dp [i] [j ] = \ sum \ limits_ {k = 0
} ^ {c [i]} {dp [i + 1] [jk × a [i]]} (j <max (a [i])) \) such complexity is \ (× 1E4 1E4 1E3 × \) , T will be apparent, a prefix and similar optimization methods, reduced complexity on the \ (1e3 × 1e4 \)

ac Code

#include<bits/stdc++.h>
#define mod 1000000007
#define N 10010
using namespace std;
int n,m,cnt1,cnt2,ans,a[N],b[N],c[N],s[N<<1],dp1[N<<1],dp2[N<<1];
void add(int &x,int y){x+=y;if(x>=mod)x%=mod;}
void del(int &x,int y){x-=y;if(x<0)x+=mod;}
void solve1()
{
    for(int i=n;i>=1;i--)
    {
        memset(s,0,sizeof(s)),s[0]=1;
        for(int k=a[i];k<m+a[i];k++)
        {
            s[k]=(s[k-a[i]]+dp1[k])%mod;
            if(k-a[i]*b[i]-a[i]>=0)
                del(s[k],dp1[k-a[i]*b[i]-a[i]]);
        }
        for(int k=0;k<m+a[i];k++)dp1[k]=s[k];
    }
}
void solve2()
{
    for(int i=n;i>=1;i--)
    {
        memset(s,0,sizeof(s)),s[0]=1;
        for(int k=a[i];k<10000;k++)
        {
            s[k]=(s[k-a[i]]+dp2[k])%mod;
            if(k-a[i]*c[i]-a[i]>=0) 
                del(s[k],dp2[k-a[i]*c[i]-a[i]]);
        }
        for(int k=0;k<10000;k++)dp2[k]=s[k];
    }
}
void get_ans(){for(int i=0;i<10000;i++)add(ans,1ll*dp1[m+i]*dp2[i]%mod);}
int main()
{
    freopen("deal.in","r",stdin),freopen("deal.out","w",stdout);
    scanf("%d%d",&n,&m),dp1[0]=dp2[0]=s[0]=1;
    for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]);
    solve1(),solve2(),get_ans(),printf("%d\n",ans);
    return 0;
}

T3- town

L country a total of \ (N \) cities and towns, they are pairwise connectivity at the start. L State plan in order to build \ (N-1 \) path, all the towns communicated with. After each build a road, you need to answer the distance between the inner communication block this road lies farthest two towns. The distance between the two towns is defined as the minimum number of road walked another seat that needs to elapse from a.

solution

Lemma: merge two trees, the diameter of the new endpoint must be an endpoint of the original two trees in diameter. I did not prove that sensibility can understand (
the diameter of the whole image seen as a forest, each connected to two points, namely merging two trees, then the novelty of the tree
merge, we put together small tree to tree in , each tree traversal time, the depth of the new modified multiplier array
and the distance between enumerated four points, the maximum diameter is the
complexity of such a \ (n \ log {n ^ 2} \) a. this I will prove that the (
worst case is obviously merge two size \ (\ frac n2 \) tree, then took 1 \ (n \ log n \)
Imagine, two size \ (\ frac n2 \ ) tree worst size from 4 \ (\ frac n4 \) tree composition, this time consuming 2 \ (\ FRAC N2 \ log {\ N2 FRAC} \) , less than \ (n \ log n \)
in turn push down total time does not exceed \ (\ log n \) a \ (n \ log n \)

ac Code

#include<bits/stdc++.h>
#define N 300010
#define K 21
using namespace std;
struct Node{int to, next;}e[N<<1];
int n,x,y,cnt,fa[N],p1[N],p2[N],head[N],dep[N],sz[N],f[N][K];
int rt,rt1,rt2,u1,u2,u3,u4,d1,d2,d3,d4,d5,d6,dis;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void add(int u,int v){e[++cnt]={v,head[u]},head[u]=cnt;}
void dfs(int x,int fa)
{
    dep[x]=dep[fa]+1,f[x][0]=fa;
    for(int i=1;i<K;i++)f[x][i]=f[f[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].next)if(e[i].to!=fa)dfs(e[i].to,x);
}
int lca(int x,int y)
{
    if(dep[x]!=dep[y])
    {
        if(dep[x]<dep[y])swap(x,y);
        for(int i=0;i<K;i++)if((dep[x]-dep[y])&(1<<i))x=f[x][i];
    }
    if(x==y)return x;
    for(int i=K-1;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
int get_dis(int x,int y){return dep[x]+dep[y]-dep[lca(x,y)]*2;}
int main()
{
    freopen("town.in","r",stdin),freopen("town.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)fa[i]=p1[i]=p2[i]=i,sz[i]=1;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y),add(x,y),add(y,x),rt,rt1=find(x),rt2=find(y);
        if(sz[rt1]<sz[rt2])dfs(x,y),sz[rt2]+=sz[rt1],fa[rt1]=rt=rt2;
        else dfs(y,x),sz[rt1]+=sz[rt2],fa[rt2]=rt=rt1;
        u1=p1[rt1],u2=p2[rt1],u3=p1[rt2],u4=p2[rt2];
        d1=get_dis(u1,u2),d2=get_dis(u3,u4),d3=get_dis(u1,u3);
        d4=get_dis(u1,u4),d5=get_dis(u2,u3),d6=get_dis(u2,u4);
        dis=max(max(d1,d2),max(max(d3,d4),max(d5,d6)));
        if(d1==dis)p1[rt]=u1,p2[rt]=u2;if(d2==dis)p1[rt]=u3,p2[rt]=u4;
        if(d3==dis)p1[rt]=u1,p2[rt]=u3;if(d4==dis)p1[rt]=u1,p2[rt]=u4;
        if(d5==dis)p1[rt]=u2,p2[rt]=u3;if(d6==dis)p1[rt]=u2,p2[rt]=u4;
        printf("%d\n",dis);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/muronglin/p/hgoi-20190813.html