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;
}