2018.7.15模拟赛

T1 数论题,先是一群恶心的特判,再用exgcd求出ax+by=gcd(a,b)的最小的解。如果c%gcd(a,b)!=0,也是无解情况。继续让原等式两边同时乘gcd(a,b)然后可以将x的最小解,y的最大解求出,之后用lcm调整x,y的大小使其能满足条件,即y/(lcm/b)+1为最后的答案,注意当y%(lcm/b)=0时要特判-1。

代码

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int MAX = 65535;

int T;
int a,b,c;

inline void exgcd(int a,int b,int &d,int &x,int &y){
    if(b==0){
        d=a;x=1;y=0;
        return;
    }
    exgcd(b,a%b,d,x,y);
    y-=a/b*x;
}

int main(){
    freopen("fuction.in","r",stdin);
    freopen("fuction.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&a,&b,&c);
        if(a==0 && b==0) {
            if(c==0) puts("ZenMeZheMeDuo");
            else puts("0");
            continue;
        }
        if(a==0){
            if(c%b==0) puts("ZenMeZheMeDuo");
            else puts("0");
            continue;
        }
        if(b==0){
            if(c%a==0) puts("ZenMeZheMeDuo");
            else puts("0");
            continue;
        }
        if(a*b<0) {
            puts("ZenMeZheMeDuo");
            continue;
        }
        if(c<0) a=-a,b=-b,c=-c;
        int d,x,y;
        exgcd(a,b,d,x,y);
        if(c%d) {
            puts("0");
            continue;
        }
        int u=c/d;int lcm=a*b/d;
        x*=u;y*=u;x%=lcm/b;
        if(x<=0) x+=lcm/b;
        y=(c-a*x)/b;
        if(y<=0){
            puts("0");
            continue;
        }
        int ans=y/(lcm/b)+1;
        if(y%(lcm/b)==0) ans--;
        if(ans>MAX) puts("ZenMeZheMeDuo");
        else printf("%d\n",ans);
    }
    return 0;
}

T2,树形dp,考场上少写了一重循环,20滚蛋,GG。我们考虑每条边的贡献,dp[x][j]表示 以x为根的子树,染了j个黑色的最大值。然后枚举每个子树,枚举j表示以x为根的子树一共染了j个黑色,再枚举k表示当前子树染了k个黑色。dp[x][j]=dp[x][j-k]+dp[u][k]+kk
kk是这条边两边的黑色乘积与白色乘积的和再乘边权。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define LL long long

using namespace std;
const int MAXN = 2005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch))  {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))   {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,ans;
int head[MAXN],cnt,siz[MAXN];
LL dp[MAXN][MAXN];
int to[MAXN<<1],nxt[MAXN<<1],val[MAXN<<1];

inline void add(int bg,int ed,int v){
    to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=v,head[bg]=cnt;
}

inline void dfs(int x,int pre){
    siz[x]=1;
    for(register int i=2;i<=m;i++) dp[x][i]=-1;
    for(register int i=head[x];i;i=nxt[i]){
        int u=to[i];
        if(u==pre) continue;
        dfs(u,x);
        siz[x]+=siz[u]; 
    }
    for(register int i=head[x];i;i=nxt[i]){
        int u=to[i];
        if(u==pre) continue;    
        for(register int j=min(m,siz[x]);j>=0;j--){
            for(register int k=0;k<=min(j,siz[u]);k++)if(dp[x][j-k]!=-1){
                LL kk=(LL)k*(m-k)*val[i]+(LL)(siz[u]-k)*(n-m-siz[u]+k)*val[i];
//              if(n-siz[u]-m+k>=0 && siz[u]-k>=0)
//                  kk=max(kk,dp[u][k]+(LL)val[i]*(LL)((LL)k*(m-k)+(LL)(siz[u]-k)*((n-siz[u]-m+k))));
//              if(m-k+1>=0 && siz[u]-k+1>=0 && n-m-siz[u]+k-1>=0 && k-1>=0)
//                  kk=max(kk,dp[u][k]+(LL)val[i]*((LL)(k-1)*(m-k+1)+(LL)(siz[u]-k+1)*(n-m-siz[u]+k-1)));
                dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[u][k]+kk);
            }
        }
    }
}

int main(){
//  freopen("coloration.in","r",stdin);
//  freopen("coloration.out","w",stdout);
    n=rd();m=rd();
    for(register int i=1;i<n;i++){
        int x=rd(),y=rd(),w=rd();
        add(x,y,w);add(y,x,w);
    }
    dfs(1,0);
    printf("%lld",dp[1][m]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40448823/article/details/81055574