AtCoder Grand Contest 002
AtCoder Grand Contest 002
A - Range Product
翻译
告诉你\(a,b\),求\(\prod_{i=a}^b i\)是正数还是负数还是零。
题解
什么鬼玩意。
#include<iostream>
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
if(a<=0&&b>=0)cout<<"Zero"<<endl;
else
{
if(a>0)cout<<"Positive"<<endl;
else if((b-a+1)%2)cout<<"Negative"<<endl;
else cout<<"Positive"<<endl;
}
return 0;
}
B - Box and Ball
翻译
有\(n\)个盒子,\(1\)号盒子里有一个红球,其他盒子里有一个白球,\(m\)个操作,每次随机将\(x_i\)中的一个球放进\(y_i\)中,求所有可能存在红球的盒子数量。
题解
什么鬼玩意。暴力模拟一下没事了。
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
bool vis[MAX];
int n,m,ans,a[MAX];
int main()
{
n=read();m=read();
vis[1]=true;
for(int i=1;i<=n;++i)a[i]=1;
while(m--)
{
int x=read(),y=read();
if(!a[x])continue;
if(vis[x])vis[y]=true;
--a[x];++a[y];
if(!a[x])vis[x]=false;
}
for(int i=1;i<=n;++i)ans+=vis[i];
printf("%d\n",ans);
return 0;
}
C - Knot Puzzle
翻译
有\(n\)根绳子,第\(i\)根的长度为\(a_i\),一开始所有绳子都被系在一起成了一条链,每次你可以选择根长度不小于\(L\)的绳子,然后解开它的任意一个结,问能否解开所有结,如果可以输出一个方案。
题解
诶,这种题目我都不会做,菜的不行啊。
我们只考虑最后一次操作,显然是要断开两个连在一起的绳子,那么它们必定相邻,并且和大于等于\(L\),所以找到这个位置之后把前后顺次解完,最后再解这个位置就好了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,L,a[MAX];
int main()
{
n=read();L=read();
for(int i=1;i<=n;++i)a[i]=read();
bool fl=false;int pos;
for(int i=1;i<n;++i)if(a[i]+a[i+1]>=L)fl=true,pos=i;
if(!fl){puts("Impossible");return 0;}
puts("Possible");
for(int i=1;i<pos;++i)printf("%d\n",i);
for(int i=n-1;i>pos;--i)printf("%d\n",i);
printf("%d\n",pos);
return 0;
}
D - Stamp Rally
翻译
给定一张图,每次询问从\(x-y\)选择两条路径,要求被经过的点数恰好为\(z\),求经过的最大编号的边的最小值。
题解
最大编号的最小值\(\rightarrow\)二分,多组询问\(\rightarrow\)整体二分。
怎么二分?两个点如果联通,答案就是联通块大小,否则就是两个点所在的联通块大小之和。
怎么维护联通块大小?并查集,反正支持撤销,搞定啦。
yyb因为把一个m打成了n而调了40分钟
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Ask{int x,y,z,id;}p[MAX],tmp[MAX];
struct edge{int x,y;}e[MAX],S[MAX];
int sz[MAX],f[MAX],top,ans[MAX];
int getf(int x){while(x!=f[x])x=f[x];return x;}
int n,m,Q;
void Work(int l,int r,int L,int R)
{
if(l==r){for(int i=L;i<=R;++i)ans[p[i].id]=l;return;}
int mid=(l+r)>>1,stop=top,t1=L-1,t2=R+1;
for(int i=l;i<=mid;++i)
{
int u=getf(e[i].x),v=getf(e[i].y);
if(u==v)continue;
if(sz[u]<sz[v])swap(u,v);
f[v]=u;sz[u]+=sz[v];S[++top]=(edge){u,v};
}
for(int i=L;i<=R;++i)
{
int x=getf(p[i].x),y=getf(p[i].y),tot;
if(x==y)tot=sz[x];else tot=sz[x]+sz[y];
if(tot>=p[i].z)tmp[++t1]=p[i];
else tmp[--t2]=p[i];
}
for(int i=L;i<=R;++i)p[i]=tmp[i];
Work(mid+1,r,t2,R);
while(top>stop)
{
int u=S[top].x,v=S[top].y;--top;
f[v]=v;sz[u]-=sz[v];
}
Work(l,mid,L,t1);
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)e[i].x=read(),e[i].y=read();
for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
Q=read();
for(int i=1;i<=Q;++i)
{
int x=read(),y=read(),z=read();
p[i]=(Ask){x,y,z,i};
}
Work(1,m,1,Q);
for(int i=1;i<=Q;++i)printf("%d\n",ans[i]);
return 0;
}
E - Candy Piles
翻译
有\(n\)堆石子,第\(i\)堆有\(a_i\)个石子。有两种操作:
- 把石子最多的那一堆给丢掉
- 把每一堆全部丢掉一个
谁拿走最后石子谁输。判断胜负情况。
题解
这样考虑,把所有\(a_i\)从大往小排序,这样子我们的两个操作可以看做在一个不规则的棋盘上走,其中\(x=i\)的上边界是\(y=a_i\),一开始位于\((0,0)\),第一个操作等价于向右走一步,第二个操作等价于向上走一步。谁走到了边界谁输。然而还是不知道怎么判断胜负情况,可以打一个表,发现\((x,y)\)这个位置的胜负情况等于\((x+1,y+1)\)的胜负情况,那么直接找到最大的合法\((x,x)\)位置然后暴力判断一下就行了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,a[MAX],ans;
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
sort(&a[1],&a[n+1]);reverse(&a[1],&a[n+1]);
for(int i=1;i<=n;++i)
if(i+1>a[i+1])
{
for(int j=i+1;a[j]==i;++j)ans^=1;
ans|=(a[i]-i)&1;
ans?puts("First"):puts("Second");
return 0;
}
return 0;
}
F - Leftmost Ball
翻译
有\(n\)种颜色的球,每种\(K\)个,现在把他们排成一行,把每种颜色的最靠左的球给染成第\(0\)种颜色。
求最终序列的方案数。
题解
我们从前往后依次把每个颜色按顺序来放,那么如果当前放的是某种颜色的第一个球,那么放的就会变成\(0\)号颜色,所以无论何时,\(0\)号颜色的数量不能少于其他颜色的数量。
可以设状态\(f[i][j]\)表示前面一共放了\(i\)个\(0\)号颜色的球,而一共出现了\(j\)种其他颜色的球,根据上面的东西,可以知道\(i\ge j\)。每次转移我们分成两种考虑。第一种就直接在后面接一个\(0\)号颜色的球,这个不需要考虑任何决策,直接转移即可,也就是\(f[i][j]+=f[i-1][j]\)。另外一种转移是选择一共新的颜色,抛去前面已经放好的\(0\)号颜色的前,抛去当前位置放下一个当前颜色的球,那么还需要在后面选择\(k-2\)个位置来放这些球,而后面剩下的空位个数显然是可以算的。首先还剩下\(n-i\)个\(0\)号颜色的球没有放,所以提供\(n-i\)个空位,前面一共只出现了\(j-1\)种颜色,所以还有\((n-j+1)*(k-1)\)个空位,但是当前的位置被钦定放这种新的颜色,所以还要减少一个位置。
也就是转移长成这个样子:
\]
时间复杂度\(O(nk)\)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 2010
#define MOD 1000000007
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,k,mx,f[MAX][MAX];
int jc[MAX*MAX],jv[MAX*MAX],inv[MAX*MAX];
int C(int n,int m){return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
int main()
{
n=read();k=read();mx=n*k;
if(k==1){puts("1");return 0;}
jc[0]=jv[0]=inv[0]=inv[1]=1;
for(int i=1;i<=mx;++i)jc[i]=1ll*jc[i-1]*i%MOD;
for(int i=2;i<=mx;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=mx;++i)jv[i]=1ll*jv[i-1]*inv[i]%MOD;
f[0][0]=1;
for(int i=1;i<=n;++i)
for(int j=0;j<=i;++j)
{
add(f[i][j],f[i-1][j]);
if(j)add(f[i][j],1ll*f[i][j-1]*(n-j+1)%MOD*C((n-i)+(n-j+1)*(k-1)-1,k-2)%MOD);
}
printf("%d\n",f[n][n]);
return 0;
}
AtCoder Grand Contest 002的更多相关文章
- AtCoder Grand Contest 002 F:Leftmost Ball
题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...
- Atcoder Grand Contest 002 F - Leftmost Ball(dp)
Atcoder 题面传送门 & 洛谷题面传送门 这道 Cu 的 AGC F 竟然被我自己想出来了!!!((( 首先考虑什么样的序列会被统计入答案.稍微手玩几组数据即可发现,一个颜色序列 \(c ...
- AtCoder Grand Contest 002 D - Stamp Rally
Description We have an undirected graph with N vertices and M edges. The vertices are numbered 1 thr ...
- AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合
原文链接https://www.cnblogs.com/zhouzhendong/p/AGC002F.html 题目传送门 - AGC002F 题意 给定 $n,k$ ,表示有 $n\times k$ ...
- 【想法题】Knot Puzzle @AtCoder Grand Contest 002 C/upcexam5583
时间限制: 2 Sec 内存限制: 256 MB 题目描述 We have N pieces of ropes, numbered 1 through N. The length of piece i ...
- [Atcoder Grand Contest 002] Tutorial
Link: AGC002 传送门 A: …… #include <bits/stdc++.h> using namespace std; int a,b; int main() { sca ...
- AtCoder Grand Contest 002题解
传送门 \(A\) 咕咕 int main(){ cin>>a>>b; if(b<0)puts(((b-a+1)&1)?"Negative": ...
- AtCoder Grand Contest 012
AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...
- AtCoder Grand Contest 011
AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...
随机推荐
- Java 浅拷贝 深拷贝
两者区别主要在于引用数据类型的属性,对于基本数据类型采用的是值传递,所以两者一样: 对于浅拷贝,引用数据类型只会进行引用传递,即复制一份引用值(内存地址)给新对象,一个对象的变化会影响到另一个的引用属 ...
- Flash导出安卓端apk
最近外甥女在学校做了一个演示视频,基于flash做的,希望小舅给她导出成可以运行在pc/android端的可执行程序.看了下过程还是蛮复杂的,还只能一天时间.重新照葫芦画瓢做一款是来不及了,由于以前基 ...
- centos 开机自启设定:
在sentos系统下,主要有两种方法设置自己安装的程序开机启动.1.把启动程序的命令添加到/etc/rc.d/rc.local文件中,比如下面的是设置开机启动httpd. #!/bin/sh # # ...
- 虚拟机中安装MAC OS X教程(适用所有电脑方法,特别是cpu不支持硬件虚拟化的电脑)
前言 之前写了一篇在Windows上搭建Object-C开发环境,并且写了一个HelloWorld程序.但真正开发苹果软件是在MAC OS X系统中(以下简称OSX)中.买不起MacBook,也没有O ...
- DevOps on AWS之Cloudformation实践篇
cloudformation入门实践 AWS cloudformation通过模板对AWS云资源进行编排和调用.并且可以通过模板代码层面的修改就可以对现有环境进行升级改造,云端业务的灵活便捷特点展现无 ...
- 纯命令行界面下安装并运行官方Android emulator
纯命令行界面指没有安装Android studio. 下载sdk-tools 可以根据实际需要下载,不需要FQ(2018-04-07) 下载后只有一个tools目录. 平台 SDK 工具包 大小 SH ...
- Trait 是什么东西
PHP官方手册里面写的内容是 自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少 ...
- Java中&、|、&&、||详解
1.Java中&叫做按位与,&&叫做短路与,它们的区别是: & 既是位运算符又是逻辑运算符,&的两侧可以是int,也可以是boolean表达式,当&两侧 ...
- 用python实现数字图片识别神经网络--启动网络的自我训练流程,展示网络数字图片识别效果
上一节,我们完成了网络训练代码的实现,还有一些问题需要做进一步的确认.网络的最终目标是,输入一张手写数字图片后,网络输出该图片对应的数字.由于网络需要从0到9一共十个数字中挑选出一个,于是我们的网络最 ...
- TeamWork#3,Week5,Scrum Meeting 11.14
根据最近项目出现的问题,我们明确了需要补充的工作,添加了几项任务. 成员 已完成 待完成 彭林江 由于网站信息更新,正在调整爬虫程序结构 更换爬虫结构 郝倩 由于网站信息更新,正在调整爬虫程序结构 更 ...