文章目录
前言
C和D题比较不错,ABE都有亿些很恶心的细节问题(尤其是E)
E题自己编写1A的读者,可以到@asta处领取8888元的现金红包(bushi)
CF65A Harry Potter and Three Spells
Description \text{Description} Description
你可以用
a
a
a 克沙子得到
b
b
b 克叶子,
c
c
c 克叶子得到
d
d
d 克金子,
e
e
e 克金子得到
f
f
f 克沙子.
给出
a
,
b
,
c
,
d
,
e
,
f
a,b,c,d,e,f
a,b,c,d,e,f,求出是否可以通过有限的沙子得到无限的金子.
Solution \text{Solution} Solution
不难得出一个有解的条件:
b
×
d
×
f
>
a
×
b
×
c
b\times d\times f>a\times b\times c
b×d×f>a×b×c.
但这是建立在六个变量均正的情况.
考虑有哪些有解的情况没有考虑.
- c = 0 , d ≠ 0 c=0,d\neq0 c=0,d=0 :金子可以无中生有,根本不需要叶子
- a = 0 , b ≠ 0 , d ≠ 0 a=0,b\ne0,d\ne0 a=0,b=0,d=0 : 叶子可以无中生有,且可以从叶子转化成金子
- e = 0 , f ≠ 0 , b ≠ 0 , d ≠ 0 e=0,f\ne0,b\ne0,d\ne0 e=0,f=0,b=0,d=0 : 沙子可以无中生有,但是这个其实不用特判,因为符合原来的式子
特判打全即可,不用开 longlong.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=4e5+100;
const int mod=998244353;
//char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
int a=read(),b=read(),c=read(),d=read(),e=read(),f=read();
if(b*d*f>a*c*e||(d&&c==0)||(d&&b&&a==0)) printf("Ron");
else printf("Hermione");
}
/*
*/
CF65B Harry Potter and the History of Magic
Description \text{Description} Description
给你 n n n 个年份 x 1... n x_{1...n} x1...n.
请你更改一些数字,使年份按时间顺序(即非递减)排列,以使其中没有任何日期晚于 2011 2011 2011 或早于 1000 1000 1000.
在每个日期中最多只能将一位数字改成别的数字.
1
≤
n
≤
10000
,
1000
≤
x
i
≤
9999
1\le n\le10000,1000\le x_i\le9999
1≤n≤10000,1000≤xi≤9999.
Solution \text{Solution} Solution
不难发现贪心策略,使前面的年份尽可能的小,一定是不劣的.
分情况讨论,如果大于前一项,从高位开始尝试往低改;如果小于前一项,就从低位开始尝试往高改即可.
最后判一下是否超过
2011
2011
2011.
实现上,有一些上下取整的细节,但整体还不算太恶心.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=4e5+100;
const int mod=998244353;
//char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
int a[1050],mi[5]={1,10,100,1000,10000};
inline int f(int x,int pos){
return x%mi[pos+1]/mi[pos];
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=1;i<=n;i++) a[i]=read();
a[0]=1000;
for(int i=1;i<=n;i++){
if(a[i]>=a[i-1]){
int d=a[i]-a[i-1];
for(int k=3;k>=0;k--){
int o=f(a[i],k);
if(!o||d<mi[k]) continue;
a[i]-=min(d/mi[k]*mi[k],o*mi[k]);break;
}
}
else{
int d=a[i-1]-a[i];
for(int k=0;k<=3;k++){
int o=9-f(a[i],k);
if(o*mi[k]<d) continue;
a[i]+=(d+mi[k]-1)/mi[k]*mi[k];
//printf("k=%d o=%d d=%d add=%d\n",k,o,d,(d+mi[k]-1)/mi[k]);
break;
}
}
//printf("%d\n",a[i]);
if(a[i]<a[i-1]){
printf("No solution");return 0;
}
}
if(a[n]>2011) printf("No solution");
else{
for(int i=1;i<=n;i++) printf("%d\n",a[i]);
}
}
/*
*/
CF65C Harry Potter and the Golden Snitch
Description \text{Description} Description
有一个金色飞贼沿着
(
x
1
,
y
1
,
z
1
)
→
(
x
2
,
y
2
,
z
2
)
→
.
.
.
→
(
x
n
,
y
n
,
z
n
)
(x_1,y_1,z_1)\to (x_2,y_2,z_2)\to ...\to (x_n,y_n,z_n)
(x1,y1,z1)→(x2,y2,z2)→...→(xn,yn,zn) 的轨迹以
v
s
v_s
vs 的速度匀速运动.
哈利的最大速度是
v
p
v_p
vp,初始位置是
(
p
x
,
p
y
,
p
z
)
(p_x,p_y,p_z)
(px,py,pz).
请求出哈利抓住金色飞贼的最快时间和抓住它的位置.
n
≤
10000
,
v
p
≥
v
s
n\le 10000,v_p\ge v_s
n≤10000,vp≥vs.
Solution \text{Solution} Solution
v
p
≥
v
s
v_p\ge v_s
vp≥vs 是本题的关键条件,这意味着本题的答案是具有单调性的.
所以二分时间判断是否可以抓到即可.
注意:
- 虽然精度只要求到 1 0 − 6 10^{-6} 10−6,但是由于坐标的计算会放大精度,所以我们的精度需要开到 1 0 − 12 10^{-12} 10−12(这里不是平方关系,只是要开小一点).
- 需要开 long double,否则精度太小可能会死循环.
- 注意不等号的精度问题.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e4+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
double t[N],sum[N],v;
double x[N],y[N],z[N];
double X,Y,Z,V;
inline double tim(double x,double y,double z){
return sqrt((x-X)*(x-X)+(y-Y)*(y-Y)+(z-Z)*(z-Z))/V;
}
bool check(double w){
for(int i=1;i<=n;i++){
if(sum[i]>=w-eps){
double o=(w-sum[i-1])/t[i];
double xx=x[i-1]+(x[i]-x[i-1])*o,yy=y[i-1]+(y[i]-y[i-1])*o,zz=z[i-1]+(z[i]-z[i-1])*o;
return tim(xx,yy,zz)-eps<w;
}
}
return false;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=0;i<=n;i++) scanf("%Lf%Lf%Lf",&x[i],&y[i],&z[i]);
scanf("%Lf%Lf%Lf%Lf%Lf",&V,&v,&X,&Y,&Z);
for(int i=1;i<=n;i++){
double d=sqrt((x[i]-x[i-1])*(x[i]-x[i-1])+
(y[i]-y[i-1])*(y[i]-y[i-1])+(z[i]-z[i-1])*(z[i]-z[i-1]));
t[i]=d/v;sum[i]=sum[i-1]+t[i];
}
if(tim(x[n],y[n],z[n])>sum[n]+eps){
printf("NO\n");return 0;
}
double st=0,ed=sum[n];
while(ed-st>eps){
double mid=(st+ed)/2;
if(check(mid)) ed=mid;
else st=mid;
}
printf("YES\n%.10Lf\n",st);
double w=st;
for(int i=1;i<=n;i++){
if(sum[i]>w-eps){
double o=(w-sum[i-1])/t[i];
double xx=x[i-1]+(x[i]-x[i-1])*o,yy=y[i-1]+(y[i]-y[i-1])*o,zz=z[i-1]+(z[i]-z[i-1])*o;
printf("%.10Lf %.10Lf %.10Lf",xx+eps,yy+eps,zz+eps);return 0;
}
}
}
/*
*/
CF65D Harry Potter and the Sorting Hat
Description \text{Description} Description
有
4
4
4 个变量
G
,
R
,
S
,
H
G,R,S,H
G,R,S,H,初始的值均为
0
0
0.
给出一个长度为
n
n
n 的字符串,从前往后进行以下过程:
- 若为 G , R , S , H G,R,S,H G,R,S,H 四者之一,则给对应的变量加一.
- 否则(为 ? ? ? ),就给四个变量中最小的加一,若有多个最小值,则给任意一个加一.
求处理完整个字符串后,四个变量是否有可能成为(非严格)最小值.
n
≤
10000
n\le 10000
n≤10000
Solution \text{Solution} Solution
设计状态为
(
i
,
a
,
b
,
c
,
d
)
(i,a,b,c,d)
(i,a,b,c,d) 表示进行到第
i
i
i 个字符,四个变量分别为
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d.
注意到,由于每次都只有在对相同的最小值加一时才会导致状态的分裂,并且可能会再后面的问号时合并状态,所以对于同一个
i
i
i,状态数是收敛的.
直接 dfs 暴搜加 hash 去重即可.
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e4+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
int x[N];
map<ll,bool>mp;
bool vis[5];
void dfs(int k,int a,int b,int c,int d){
int mn=min(a,min(b,min(c,d)));
if(k>n){
if(a==mn) vis[1]=1;
if(b==mn) vis[2]=1;
if(c==mn) vis[3]=1;
if(d==mn) vis[4]=1;
return;
}
ll o=1ll*a*(n+1)*(n+1)*(n+1)+1ll*b*(n+1)*(n+1)+1ll*c*(n+1)+d;
if(mp[o]) return;
if(x[k]){
if(x[k]==1) dfs(k+1,a+1,b,c,d);
else if(x[k]==2) dfs(k+1,a,b+1,c,d);
else if(x[k]==3) dfs(k+1,a,b,c+1,d);
else if(x[k]==4) dfs(k+1,a,b,c,d+1);
}
else{
if(a==mn) dfs(k+1,a+1,b,c,d);
if(b==mn) dfs(k+1,a,b+1,c,d);
if(c==mn) dfs(k+1,a,b,c+1,d);
if(d==mn) dfs(k+1,a,b,c,d+1);
}
mp[o]=1;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
char c;
for(int i=1;i<=n;i++){
scanf(" %c",&c);
if(c=='G') x[i]=1;
else if(c=='H') x[i]=2;
else if(c=='R') x[i]=3;
else if(c=='S') x[i]=4;
}
dfs(1,0,0,0,0);
if(vis[1]) printf("Gryffindor\n");
if(vis[2]) printf("Hufflepuff\n");
if(vis[3]) printf("Ravenclaw\n");
if(vis[4]) printf("Slytherin\n");
}
/*
*/
CF65E Harry Potter and Moving Staircases
Description \text{Description} Description
有一个
n
n
n 个点
m
m
m 条边的无向图,哈利初始在结点
1
1
1,哈利可以沿着边任意移动,过程中任意时刻可以选择一条边,改变它的一个端点,但是每条边只能被修改一次.
请构造一种方案使哈利走遍所有楼层,或者报告无解.
n
≤
1
0
5
,
m
≤
2
×
1
0
5
n\le 10^5,m\le 2\times10^5
n≤105,m≤2×105
Solution \text{Solution} Solution
阴间大特判题.
容易找到一种比较正确的整体方案:dfs,过程中——
- 若出边连向走过的结点,则直接把边改向一个未走过的结点,递归 dfs.
- 若出边连向未走过的结点,则先递归 dfs,回溯时在把边改向一个未走过的结点,递归 dfs.
不难发现这样一定是最优的.
然后就是 通过观察 WA 的数据 处理亿点点细节问题:
- 改边连向的点应该优先连向有度数的点.
- 有可能会出现 1 1 1 没有度数但存在解的情况,这时候需要尝试把一条边直接改为连向 1 1 1,同时这个边不应该是一条边连接两个点的简单图形.(否则改完还是会死掉)
- 改为连向 1 1 1 的边应该优先选择成环的边,这样会更优.
具体实现留给读者自行思考.(或者参考我实现丑的一批的代码)
Code \text{Code} Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=4e5+100;
const double eps=1e-12;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
struct node{
int to,nxt;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y){
p[++cnt]=(node){y,fi[x]};fi[x]=cnt;
return;
}
int jd[N],du[N];
set<int>s1,s2;
int dfn[N<<2],tim,tot;
struct edge{
int x,y,id;
}e[N];
int siz[N];
int ans[N],num;
int flag,O,ID;
void print(){
int pl(1);
if(!O) flag=0;
printf("YES\n%d\n",tot+flag);
for(int i=1;i<=tim+1;i++){
if(dfn[i]) ans[++num]=dfn[i];
else{
printf("%d ",num);
for(int j=1;j<=num;j++) printf("%d ",ans[j]);
putchar('\n');
num=0;
if(pl<=tot){
printf("%d %d %d\n",e[pl].id,e[pl].x,e[pl].y);
++pl;
}
}
if(i==1&&flag){
printf("1 1\n%d %d 1\n",ID,O);num=0;
}
}
return;
}
int fa[N];
vector<int> v[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
bool vis[N];
void dfs(int x){
dfn[++tim]=x;vis[x]=1;
for(int i=fi[x];~i;i=p[i].nxt){
if(jd[i]==1) continue;
int f=jd[i];
jd[i]=jd[i^1]=1;
int to=p[i].to;
//printf("x=%d to=%d\n",x,to);
dfs(to);
dfn[++tim]=x;
if((!s1.empty()||!s2.empty())&&!f){
int o;
if(!s1.empty()) o=(*s1.begin()),s1.erase(o);
else o=(*s2.begin()),s2.erase(o);
//printf("x=%d o=%d\n",x,o);
dfn[++tim]=0;e[++tot]=(edge){x,o,i/2+1};
dfs(o);
dfn[++tim]=x;
}
}
return;
}
int E;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
memset(fi,-1,sizeof(fi));cnt=-1;
n=read();m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
e[i].x=read();e[i].y=read();
++du[e[i].x];++du[e[i].y];
if(find(e[i].x)==find(e[i].y)){
E=i;
}
else fa[find(e[i].x)]=find(e[i].y);
}
if(du[1]==0){
flag=1;
if(E){
e[E].y=1;O=e[E].x;ID=E;
}
else{
for(int i=1;i<=m;i++){
if(du[e[i].x]<=1) swap(e[i].x,e[i].y);
if(du[e[i].x]>1){
e[i].id=1;O=e[i].x;ID=i;
e[i].y=1;break;
}
}
}
}
memset(du,0,sizeof(du));
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int x=e[i].x,y=e[i].y;
addline(x,y);addline(y,x);
fa[find(x)]=find(y);
++du[x];++du[y];
if(e[i].id) jd[cnt]=jd[cnt^1]=2;
}
//for(int i=1;i<=n;i++) debug("i=%d fa=%d\n",i,fa[i]);
for(int i=2;i<=n;i++){
if(i==find(i)&&find(1)!=i){
if(du[i]) s1.insert(i);
else s2.insert(i);
}
}
dfs(1);
if(!s1.empty()||!s2.empty()) printf("NO\n");
else print();
return 0;
}
/*
*/