赛中通过
B Coffee Chicken(递归)
n个串的生成方式如下,
第一个串S(1)="COFFEE",第二个串S(2)="CHICKEN",
第n个串S(n) = S(n-2) :: S(n-1),::表示字符串的拼接
给出n(n<=500),k(k<=min(|S(n)|,1e12)),
要求输出第n个串,从第k个字符开始往后10个字符,
如果到串的结尾也不足10个字符,就输出到串的结尾
考虑每个字符在哪里显然更便捷一点,不然得分字符串拼接来讨论
赛中讨论了若干,递归搞过去了,赛后补一补别人10minAC的简洁代码
递归:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=1e13;
int t;
char a[]={"COFFEE"},b[]={"CHICKEN"};
ll fib[505],n,k,v;
void init()
{
fib[1]=6;
fib[2]=7;
for(int i=3;i<=500;++i)
fib[i]=min(INF,fib[i-1]+fib[i-2]);
}
void gt(ll n,ll k)
{
if(n==1){putchar(a[k-1]);return;}
if(n==2){putchar(b[k-1]);return;}
if(k<=fib[n-2])gt(n-2,k);
else gt(n-1,k-fib[n-2]);
}
int main()
{
init();
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&k);
for(int i=0;i<=9;++i)
if(k+i<=fib[n])gt(n,k+i);
puts("");
}
return 0;
}
循环:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=1e13;
int t;
char a[]={"COFFEE"},b[]={"CHICKEN"};
ll fib[505],n,k,v;
void init()
{
fib[1]=6;
fib[2]=7;
for(int i=3;i<=500;++i)
fib[i]=min(INF,fib[i-1]+fib[i-2]);
}
void gt(ll n,ll k)
{
while(n>2)
{
if(k<=fib[n-2])n-=2;
else k-=fib[n-2],n--;
}
if(n==1)putchar(a[k-1]);
if(n==2)putchar(b[k-1]);
}
int main()
{
init();
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&k);
for(int i=0;i<=9;++i)
if(k+i<=fib[n])gt(n,k+i);
puts("");
}
return 0;
}
D Han Xin and His Troops(Python+扩展CRT)
一道扩展CRT裸题,姿势不好会爆ll甚至爆__int128
之前的C++大数板子,不带大数%大数和大数/大数,然后就gg了
于是强行把C++的扩展CRT板子改成python的,java的回头再补
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a % b)
def exgcd(a, b):
if b == 0:
return 1, 0, a # x=1 y=0 ans=a
x, y, r = exgcd(b, a % b)
tmp = x
x1 = y
y1 = tmp - (a // b) * y
return x1, y1, r
def inv(a, b):
x, y, r = exgcd(a, b)
while x < 0:
x += b
return x
def excrt(n, m):
M = []
C = []
for i in range(n):
p, q = map(int, input().split())
M.append(p)
C.append(q)
for i in range(1, n):
M1 = M[i - 1]
M2 = M[i]
C2 = C[i]
C1 = C[i - 1]
T = gcd(M1, M2)
if (C2 - C1) % T != 0:
print('he was definitely lying')
return
M[i] = M1 * M2 // T
C[i] = (inv(M1 // T, M2 // T) * (C2 - C1) // T) % (M2 // T) * M1 + C1
C[i] = (C[i] % M[i] + M[i]) % M[i]
if C[n - 1] > m:
print('he was probably lying')
return
print(C[n - 1])
n, m = map(int, input().split())
excrt(n, m)
E Hilbert Sort(递归分形 排序)
队友抄了个希尔伯特曲线求距离的板子
四叉树和希尔伯特曲线做空间索引_hilbert 四叉树-CSDN博客
先求出每个位置对应的希尔伯特距离,再排序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int const maxn=1e6+5;
struct node{
ll x,y,d;
}p[maxn];
bool cmp(node a,node b){
return a.d<b.d;
}
void rot(ll n, ll *x, ll *y, ll rx, ll ry);
ll xy2d (ll n, ll x, ll y){
ll rx, ry, s, d=0;
for (s=n/2; s>0; s/=2)
{
rx = (x & s) > 0;
ry = (y & s) > 0;
d += s * s * ((3 * rx) ^ ry);
rot(s, &x, &y, rx, ry);
}
return d;
}
void rot(ll n, ll *x, ll *y, ll rx, ll ry){
if (ry == 0){
if (rx == 1){
*x = n-1 - *x;
*y = n-1 - *y;
}
ll t = *x;
*x = *y;
*y = t;
}
}
int main(){
ll n,k;
scanf("%lld%lld",&n,&k);
ll len=1<<k;
for(int i=0;i<n;i++){
scanf("%lld%lld",&p[i].x,&p[i].y);
p[i].d=xy2d(len,p[i].y-1,p[i].x-1);
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++) printf("%lld %lld\n",p[i].x,p[i].y);
}
F Popping Balloons(线段树)
n(1<=n<=1e5)个气球,第i个气球在(xi,yi)(0<=xi,yi<=1e5)
要求划爆三行三列,使得划爆的气球最大,输出划爆的气球数
要求这三行两两行间距恰为r,三列两两列间距恰为r,r为给定距离(1<=r<=1e5)
线段树先按行在对应行i放入(i,i+r,i+2r)行的气球,表示枚举第i行作最左端划破行时的结果
枚举列j作最左端划破列j时,先将j,j+r,j+2r内vector里存的对应行的答案去掉,
避免重复统计,更新答案,再把去掉的答案加回来,
由于i存的是i,i+r,i+2*r,所以vector内行v应消除对应位置v,v-r,v-2*r的影响,此三处存了行v的气球
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=1e5+10;
const int mx=1e5+1;
int n,r,x,y,dat[4*N],ans;
vector<int>row[N],col[N];
void upd(int p,int l,int r,int x,int v)
{
if(l==r)
{
dat[p]+=v;
return;
}
int mid=(l+r)/2;
if(x<=mid)upd(p<<1,l,mid,x,v);
else upd(p<<1|1,mid+1,r,x,v);
dat[p]=max(dat[p<<1],dat[p<<1|1]);
}
void undo(vector<int> &a,int op)
{
for(int v:a)
{
upd(1,1,mx,v,op);
if(v-r>=1)upd(1,1,mx,v-r,op);
if(v-2*r>=1)upd(1,1,mx,v-2*r,op);
}
}
int main()
{
scanf("%d%d",&n,&r);
for(int i=1;i<=n;++i)
{
scanf("%d%d",&x,&y);
x++;y++;
row[x].pb(y);
col[y].pb(x);
}
for(int i=1;i<=mx;++i)
{
int res=row[i].size();
if(i+r<=mx)res+=row[i+r].size();
if(i+2*r<=mx)res+=row[i+2*r].size();
upd(1,1,mx,i,res);
}
for(int i=1;i<=mx;++i)
{
int tmp=col[i].size();
if(i+r<=mx)tmp+=col[i+r].size();
if(i+2*r<=mx)tmp+=col[i+2*r].size();
undo(col[i],-1);
if(i+r<=mx)undo(col[i+r],-1);
if(i+2*r<=mx)undo(col[i+2*r],-1);
ans=max(ans,dat[1]+tmp);
undo(col[i],1);
if(i+r<=mx)undo(col[i+r],1);
if(i+2*r<=mx)undo(col[i+2*r],1);
}
printf("%d\n",ans);
return 0;
}
H Stammering Chemists(分类讨论)
T(T<=2e5)组样例,每次给出5条边,判断给定图是以上哪种图
根据度为2、3、4的关系可以确定大部分,
3-methylpentane和2-methylpentane,要对度为3的树根dfs,确定深度
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
int t;
int u,v,deg[7],num[7],mx;
vector<int>E[7];
void dfs(int u,int fa,int dep)
{
mx=max(mx,dep);
for(int v:E[u])
if(v!=fa)dfs(v,u,dep+1);
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(deg,0,sizeof deg);
memset(num,0,sizeof num);
mx=0;
for(int i=1;i<=6;++i)
E[i].clear();
for(int i=1;i<6;++i)
{
scanf("%d%d",&u,&v);
E[u].pb(v),E[v].pb(u);
deg[u]++;
deg[v]++;
}
for(int i=1;i<=6;++i)
num[deg[i]]++;
if(num[2]==4)puts("n-hexane");
else if(num[4]==1)puts("2,2-dimethylbutane");
else if(num[3]==2)puts("2,3-dimethylbutane");
else
{
int i;
for(i=1;i<=6;++i)
if(deg[i]==3)
{
dfs(i,-1,0);
break;
}
if(mx==3)puts("2-methylpentane");
else puts("3-methylpentane");
}
}
return 0;
}
赛后补题
J Wood Processing(斜率dp)
2019牛客暑期多校训练营(第十场) J.Wood Processing(斜率dp)_processing斜率-CSDN博客