传送门

\(A\)

根据裴蜀定理显然要\(k|\gcd(a_1,...,a_n)\),顺便注意不能造出大于\(\max(a_1,...,a_n)\)的数

int n,g,k,x,mx;
int main(){
scanf("%d%d",&n,&k);
fp(i,1,n)scanf("%d",&x),g=__gcd(g,x),cmax(mx,x);
puts(k%g==0&&k<=mx?"POSSIBLE":"IMPOSSIBLE");
return 0;
}

\(B\)

对每个人开一个指针,表示他是参加了哪个运动,然后每次把参加人数最多的运动强制不选,同时更新每个人的指针。一直做到指针越界为止,取最优值即可

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=305;
int mp[N][N],cnt[N],id[N],bg[N],vis[N],res,mx,n,m;
int main(){
scanf("%d%d",&n,&m);
fp(i,1,n)fp(j,1,m)scanf("%d",&mp[i][j]);
fp(i,1,n)bg[i]=1,++cnt[mp[i][1]];
res=2333;
while(2333){
mx=0;fp(i,1,m)cmax(mx,cnt[i]);
cmin(res,mx);
fp(i,1,m)if(cnt[i]==mx)vis[i]=1;
fp(i,1,n)while(bg[i]<=m&&vis[mp[i][bg[i]]])++bg[i];
fp(i,1,n)if(bg[i]>m)return printf("%d\n",res),0;
fp(i,1,m)cnt[i]=0;
fp(i,1,n)++cnt[mp[i][bg[i]]];
}
return 0;
}

\(C\)

先考虑二维的情况,即总共有\(n=x+y\)个人,每个人有金币\(a_i\)或银币\(b_i\),那么先假设所有人都取银币,加上前\(x\)大的\(a_i-b_i\)就行了。如果总的个数大于\(n\),那么按\(a_i-b_i\)从大到小排序后,取金币的人必然全部在取银币的人的左边,即存在一个中间点\(k\),满足取金币的人在\([1,k]\),取银币的人在\([k+1,n]\)

对于三维,我们假设所有人都选铜币,并令\(a_i-=c_i,b_i-=c_i\),那么此时转化为之前那种二维的情况了,用堆维护就可以了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define gg(u) for(int &i=cur[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll f[N],g[N],sum,res;int a[N],b[N],c[N],id[N],x,y,z,n,sz;
priority_queue<int,vector<int>,greater<int> >q;
inline bool cmp(const int &x,const int &y){return a[x]-b[x]>a[y]-b[y];}
inline void ins(R int x){sum+=x,q.push(x),++sz;}
inline void del(){sum-=q.top(),q.pop(),--sz;}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d%d",&x,&y,&z),n=x+y+z;
fp(i,1,n){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
a[i]-=c[i],b[i]-=c[i],id[i]=i;
}
sort(id+1,id+1+n,cmp);
sum=sz=0;while(!q.empty())q.pop();
fp(i,1,n){
ins(a[id[i]]);
while(sz>x)del();
if(sz==x)f[i]=sum;
}
sum=sz=0;while(!q.empty())q.pop();
fd(i,n,1){
ins(b[id[i]]);
while(sz>y)del();
if(sz==y)g[i]=sum;
}
res=-1e18;
fp(i,x,n-y)cmax(res,f[i]+g[i+1]);
fp(i,1,n)res+=c[i];
printf("%lld\n",res);
return 0;
}

\(D\)

我是个\(zz\)……

首先对于每条边,设它两边的\(size\)里较小的那个为\(s\),它的权值为\(w\),那么它的贡献上界是\(s\times w\),那么答案上界就是\(\sum s\times w\)

然而上界不可能达到的,我们考虑该减去那些

假设重心是一条边,即两边的\(size\)大小都是\({n\over 2}\),那么对于除了重心的这条边,我们都可以令它被经过次数达到上界,那么答案就是上界减去这条边的权值

假设重心是一个点,那么除了重心到某个子节点的一条边,我们也可以让这些边都达到上界,那么答案就是上界减去重心到子节点的边权中最小的就是了

//quming
#include<bits/stdc++.h>
#define R register
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
typedef pair<ll,int> pi;
const int N=1e5+5;
struct eg{int v,nx,w;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v,R int w){e[++tot]={v,head[u],w},head[u]=tot;}
inline int min(R int x,R int y){return x<y?x:y;}
ll res;int sz[N],rt,rv,op,mmx,n;
void dfs(int u,int fa,ll dis){
sz[u]=1;
R int mx=0;
go(u)if(v!=fa){
dfs(v,u,dis+e[i].w),sz[u]+=sz[v];
res+=1ll*min(sz[v],n-sz[v])*e[i].w<<1;
if((sz[v]<<1)==n)op=1,rv=e[i].w;
cmax(mx,sz[v]);
}
cmax(mx,n-sz[u]);
if(cmin(mmx,mx))rt=u;
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n),mmx=n+1;
for(R int i=1,u,v,w;i<n;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
dfs(1,0,0);
if(op&1)res-=rv;
else{
R int mn=0x3f3f3f3f;
go(rt)cmin(mn,e[i].w);
res-=mn;
}
printf("%lld\n",res);
return 0;
}

\(E\)

越来越觉得自己好蠢了……

我们先从原点开始考虑,设\(c(x,y)\)表示从原点到\(x,y\)的方案数\((x\geq 0,y\geq 0)\),这个显然为\({x+y\choose x}\)

然后开始推倒

\[\begin{aligned}
\sum_{y=0}^Y c(X,y)=c(X+1,Y)
\end{aligned}
\]

就是说走到\((X+1,Y)\)的方案,就等价于我们枚举在第\(X\)行的哪一列往下走再往右

\[\begin{aligned}
\sum_{x=0}^X\sum_{y=0}^Y c(x,y)=c(X+1,Y+1)-1
\end{aligned}
\]

用前面那个柿子带进去就可以了

\[\begin{aligned}
\sum_{x=X_1}^{X_2}\sum_{y=Y_1}^{Y_2} c(x,y)=C(X_2+1,Y_2+1)-c(X_1,Y_2+1)-c(X_2+1,Y_1)+c(X_1,Y_1)
\end{aligned}
\]

相当于是子矩阵求和,那么变成四个前缀和减一减就好了

然后我们发现一个矩阵可以拆成四个单点求和的形式!

然后我们考虑,起点,中间点,终点的范围都是一个矩阵,如果我们枚举中间点,那么就可以把起点和终点的求和给拆成四个单点的形式,这样就可以\(O(16)\)计算一个中间点的贡献了

考虑如果一条路径经过中间点的那个矩阵,那么贡献就是这条路径和矩阵相交的点的个数,也就是说这条路径要乘上这个个数

我们枚举这条路径是从哪里进矩阵的,从哪里出矩阵的,假设分别是从\((x,y)\)进且从\((xx,yy)\)出,那么贡献就是\(xx-x+yy-y+1\)

那么我们只枚举路径进矩阵的位置,对于路径数乘上\((-x-y)\),再枚举路径出矩阵的位置,对于路径数乘上\(xx+yy+1\),这样我们发现每条合法的路径都会被计算恰好贡献次,所以就没问题了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=2e6+5;
int fac[N],ifac[N];
void init(int n=2e6){
fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
inline int calc(R int x,R int y,R int xx,R int yy){
R int res=C(x+y,x);
upd(res,C(xx+1+yy+1,xx+1));
upd(res,P-C(x+yy+1,x));
upd(res,P-C(y+xx+1,y));
return res;
}
int x[15],y[15],res;
inline int t1(R int xx,R int yy){
return calc(xx-x[2],yy-y[2],xx-x[1],yy-y[1]);
}
inline int t2(R int xx,R int yy){
return calc(x[5]-xx,y[5]-yy,x[6]-xx,y[6]-yy);
}
int main(){
// freopen("testdata.in","r",stdin);
init();
fp(i,1,6)scanf("%d",&x[i]);
fp(i,1,6)scanf("%d",&y[i]);
fp(i,x[3],x[4]){
upd(res,1ll*(P-y[3]-i)*t1(i,y[3]-1)%P*t2(i,y[3])%P);
upd(res,1ll*(y[4]+1+i)*t1(i,y[4])%P*t2(i,y[4]+1)%P);
}
fp(j,y[3],y[4]){
upd(res,1ll*(P-x[3]-j)*t1(x[3]-1,j)%P*t2(x[3],j)%P);
upd(res,1ll*(x[4]+1+j)*t1(x[4],j)%P*t2(x[4]+1,j)%P);
}
printf("%d\n",res);
return 0;
}

\(F\)

首先根据每个点的子节点的个数,是可以判断该节点需要填奇数还是偶数的,如果这个奇偶性在两棵树上不同那么显然无解了

否则的话,对于偶节点,我们令其为\(0\),对于每个奇节点的子树中一定有\(2k+1\)个奇节点,我们把这些搞成\(k\)组匹配,对于\((u,v)\)的一组匹配,令\(a_u=1,a_v=-1\)就行了这样子树中的总和的绝对值一定是\(1\)

而对于我们连的边,它一定是一个二分图(否则就会有一个点连了两条边且来自同一棵子树),那么直接黑白染色确定方案就行了

//quming
#include<bits/stdc++.h>
#define R register
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=2e5+5;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
vector<int>t1[N],t2[N];
int a1[N],a2[N],st[N],b[N],rt1,rt2;
int n,top;
void dfs1(int u){
for(auto v:t1[u])dfs1(v);
if(a1[u])st[++top]=u;
while(top>=2){
add(st[top],st[top-1]),add(st[top-1],st[top]);
top-=2;
}
}
void dfs2(int u){
for(auto v:t2[u])dfs2(v);
if(a2[u])st[++top]=u;
while(top>=2){
add(st[top],st[top-1]),add(st[top-1],st[top]);
top-=2;
}
}
void dfs(int u,int c){
b[u]=c;
go(u)if(!b[v])dfs(v,-c);
}
int main(){
scanf("%d",&n);
fp(i,1,n)a1[i]=a2[i]=1;
for(R int i=1,fa;i<=n;++i){
scanf("%d",&fa);
if(fa==-1)rt1=i;else t1[fa].pb(i),a1[fa]^=1;
}
for(R int i=1,fa;i<=n;++i){
scanf("%d",&fa);
if(fa==-1)rt2=i;else t2[fa].pb(i),a2[fa]^=1;
}
fp(i,1,n)if(a1[i]!=a2[i])return puts("IMPOSSIBLE"),0;
puts("POSSIBLE");
top=0,dfs1(rt1);
top=0,dfs2(rt2);
fp(i,1,n)if(a1[i]&&!b[i])dfs(i,1);
fp(i,1,n)printf("%d ",b[i]);
return 0;
}

AtCoder Grand Contest 018题解的更多相关文章

  1. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  2. AtCoder Grand Contest 018 D - Tree and Hamilton Path

    题目传送门:https://agc018.contest.atcoder.jp/tasks/agc018_d 题目大意: 给定一棵\(N\)个点的带权树,求最长哈密顿路径(不重不漏经过每个点一次,两点 ...

  3. Atcoder Grand Contest 054 题解

    那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...

  4. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  5. AtCoder Grand Contest 031题解

    题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...

  6. AtCoder Grand Contest 018 A

    A - Getting Difference Time limit時間制限 : 2sec / Memory limitメモリ制限 : 256MB 配点 : 300 点 問題文 箱に N 個のボールが入 ...

  7. AtCoder Grand Contest 039 题解

    传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...

  8. AtCoder Grand Contest 017题解

    传送门 \(A\) 直接转移就是了 typedef long long ll; const int N=55; ll f[N][2];int a[N],n,p; int main(){ scanf(& ...

  9. AtCoder Grand Contest 015题解

    传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...

随机推荐

  1. IdentityServer4实现Oauth2.0四种模式之隐藏模式

      接上一篇:IdentityServer4实现OAuth2.0四种模式之密码模式,密码模式将用户的密码暴露给了客户端,这无疑是不安全的,隐藏模式可以解决这个问题,由用户自己在IdentityServ ...

  2. mongoose 警告信息 { useNewUrlParser: true } { useUnifiedTopology: true }

    问题: 解决:

  3. Python标准库-datatime和time

    Python标准库-datatime和time 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.标准库datatime 1>.datatime模块 #!/usr/bin/e ...

  4. vmware联网解决方案:host-only共享上网

    一.需求说明 vmware通过桥接的方式可以上外网,但是虚拟机的IP地址必须和物理网卡在同一网段,上网环境不同虚拟机必须跟着换ip地址很麻烦,所以最好是采用host-only方式上网. 特别是做架构实 ...

  5. 【独家】K8S漏洞报告 | 近期bug fix解读

    安全漏洞CVE-2019-3874分析 Kubernetes近期重要bug fix分析 Kubernetes v1.13.5 bug fix数据分析 ——本周更新内容 安全漏洞CVE-2019-387 ...

  6. Optaplanner与Google OR-Tools的区别

    在规划相关的项目工作中,近两年我们的项目主要使用的是Optaplanner作为规划引擎,其核心也是一个的规划求解器(Solver).但作为另一个著名开源求解器Google OR-Tools(下称OR- ...

  7. 局部敏感哈希算法(Locality Sensitive Hashing)

    from:https://www.cnblogs.com/maybe2030/p/4953039.html 阅读目录 1. 基本思想 2. 局部敏感哈希LSH 3. 文档相似度计算 局部敏感哈希(Lo ...

  8. Java精通并发-锁粗化与锁消除技术实例演示与分析

    在上一次https://www.cnblogs.com/webor2006/p/11446473.html中对锁的升级进行了一个比较详细的理论化的学习,先回忆一下: 编译器对于锁的优化措施: 锁消除技 ...

  9. Route all trafic for specific ip over specific network interface

    15 I have a linux server that needs to get some routing. I'm fairly new at this and i don't find any ...

  10. 《CoderXiaoban》第八次团队作业:Alpha冲刺 3

    项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 Coderxiaoban团队 作业学习目标 (1)掌握软件测试基 ...