title :2022牛客暑期多校训练营5 题解
date : 2022-9-21
tags : ACM,练习记录
author : Linno
2022牛客暑期多校训练营5 题解
题目链接 :https://ac.nowcoder.com/acm/contest/33190
补题进度 :9/11
温馨提示:这场因为质量太差unr了。
A-Don’t Starve
因为数据太水,赛时写的记忆化搜索过了,给大家看一眼。(其实是没补题
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
using namespace std;
const int N=2007;
const int mod=1e9+7;
int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
struct node{
int x,y;
}s[N];
struct E{
int v,w;
bool operator <(E B)const{
return w<B.w;
}
};
vector<E>G[N];
int n,vis[N],dp[N][N],ans=0;
inline int dis(node A,node B){
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
inline int dfs(int x,int lst){
if(G[x][0].w>=lst) return 1; //如果没有边满足条件
int L=0,R=n-2,M;
while(L<R){
M=((L+R+1)>>1);
if(G[x][M].w<lst) L=M; //二分找到最大的一条满足的边
else R=M-1;
}
int idx=L;
if(idx<=vis[x]) return dp[x][idx]+1; //x已经记录过这条边能走到的点数
for(int i=vis[x]+1;i<=idx;++i){ //转移前i条边可以走到的点数
int v=G[x][i].v,w=G[x][i].w;
if(i>0) dp[x][i]=max(dp[x][i-1],dfs(v,w));
else dp[x][i]=dfs(v,w);
}
vis[x]=idx;
return dp[x][idx]+1;
}
void Solve(){
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d%d",&s[i].x,&s[i].y);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(i==j) continue;
G[i].emplace_back((E){j,dis(s[i],s[j])});
}
sort(G[i].begin(),G[i].end()); //按边权从小到大排序
}
memset(vis,-1,sizeof(vis));
for(int i=1;i<=n;++i){
ans=max(ans,dfs(i,s[i].x*s[i].x+s[i].y*s[i].y));
}
write(ans);putchar('\n');
}
signed main(){
// srand(time(0));
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(T--){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}
B-Watches
二分板。
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,m,a[N],b[N];
bool check(int x){
int res=0,cnt=0;
for(int i=1;i<=n;++i){
b[i]=a[i]+x*i;
}
sort(b+1,b+1+n);
for(int i=1;i<=n;++i){
if(res+b[i]<=m){
cnt++;
res+=b[i];
}else{
break;
}
}
if(cnt>=x) return true;
return false;
}
void Solve(){
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>a[i];
int L=0,R=n,M;
while(R-L>1){
M=(L+R)/2;
if(check(M)) L=M;
else R=M;
}
if(check(R)) L=R;
cout<<L<<"\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(T--){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}
C-Bit Transmission
这题数据也有大锅,以下是赛时过的代码。
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
//#define inf 0x3f3f3f3f
//#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,op,flag,vis[N][3];
char str[10];
void Solve(){
flag=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<3*n;++i){
scanf("%d%s",&op,str);
if(str[0]=='Y'){
vis[op][1]++;
}else{
vis[op][0]++;
}
}
for(int i=0;i<n;++i){
if(vis[i][0]>1&&vis[i][1]>1) flag=1; //存在多次错误回答
if(vis[i][0]==vis[i][1]) flag=1; //都问了一次
if(vis[i][0]+vis[i][1]<=1) flag=1;
}
if(flag) puts("-1");
else{
for(int i=0;i<n;++i){
if(vis[i][0]>vis[i][1]) putchar('0');
else putchar('1');
}
putchar('\n');
}
}
signed main(){
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(scanf("%d",&n)!=EOF){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}
D-Birds in the tree
树形dp。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
vector<int> edge[1000005];
int a[1000005],f[1000005],g[1000005],ans;
void dfs(int x)
{
f[x]=g[x]=1;
for (int i=0;i<edge[x].size();++i)
{
int y=edge[x][i];
dfs(y);
f[x]=f[x]*(f[y]+1)%mod;
g[x]=g[x]*(g[y]+1)%mod;
}
if (a[x]==0) { g[x]--; g[x]=(g[x]+mod)%mod;}
else { f[x]--; f[x]=(f[x]+mod)%mod; }
ans=ans+f[x]+g[x];
ans%=mod;
for (int i=0;i<edge[x].size();++i)
if (a[x]==0) {
int y=edge[x][i];
ans=(ans-g[y]+mod)%mod;
}
else
{
int y=edge[x][i];
ans=(ans-f[y]+mod)%mod;
}
}
signed main()
{
int n;
while (scanf("%lld",&n)!=EOF)
{
getchar();
for (int i=1;i<=n;++i)
{ a[i]=getchar()-'0'; f[i]=g[i]=0; edge[i].clear(); }
for (int i=1;i<n;++i)
{
int x,y;
scanf("%lld%lld",&x,&y);
edge[x].push_back(y);
}
ans=0;
dfs(1);
printf("%lld\n",ans);
}
return 0;
}
E-Fraction Game
没补。
F-A Stack of CDs
就是求圆的周长并,随便去套个板子简单粗暴。
#include<bits/stdc++.h>
using namespace std;
const int N = 2005;
const double pi = acos(-1.0);
int read() {
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
int cnt, n;
struct dat {double l, r;}opt[N];
bool operator < (dat a, dat b) {return a.l < b.l;}
struct C {
double x, y, r;
C(double a = 0, double b = 0, double c = 0) : x(a), y(b), r(c) {}
C operator - (C a) {return C(x - a.x, y - a.y, 0);}
double operator ^ (C a) {return x * a.x + y * a.y;}
}p[N];
double sqr(double x) {return x * x;}
double sqr(C a) {return a ^ a;}
double angle(C p) {return atan2(p.y, p.x);}
double angle(double a, double b, double c) {return acos((a * a + b * b - c * c) / (2 * a * b));}
void add(double a, double b) {opt[++cnt].l = a; opt[cnt].r = b;}
void Solve(C u, C v, double dis) {
double t1 = angle(u - v), t2 = angle(u.r, dis, v.r);
double l = t1 - t2, r = t1 + t2;
if(l < 0) l += 2 * pi;
if(r < 0) r += 2 * pi;
if(l > r) {add(0, r); add(l, 2 * pi);}
else add(l, r);
}
double calc() {
sort(opt + 1, opt + cnt + 1); double l = -10, r = -10, ret = 0;
for(int i = 1;i <= cnt; ++i)
if(opt[i].l > r) {ret += r - l; l = opt[i].l; r = opt[i].r;}
else r = max(r, opt[i].r);
ret += r - l; return 2 * pi - ret;
}
signed main() {
scanf("%d", &n);
for(int i = n; i; --i) scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].r);
double ans = 0;
for(int i = 1, j;i <= n; ++i) {
cnt = 0;
for(j = 1;j < i; ++j) {
double dis = sqrt(sqr(p[j] - p[i]));
if(p[j].r - p[i].r > dis) break;
if(p[j].r + p[i].r > dis && fabs(p[j].r - p[i].r) < dis) Solve(p[i], p[j], dis);
}
if(j == i) ans += p[i].r * calc();
}
printf("%.12lf\n", ans);
return 0;
}
G-KFC Crazy Thursday
#include <bits/stdc++.h>
using namespace std;
struct dat
{
unsigned long long f,c,k;
}f[1000005];
unsigned long long g[1000005],hash_head[1000005],hash_tail[1000005],len;
unsigned long long ansc,ansf,ansk;
bool check(int x,int pos)
{
int l=pos-x;
int r=pos+x;
if (l<1||r>len) return false;
if (hash_head[r]-hash_head[pos-1]*g[x+1]==hash_tail[l]-hash_tail[pos+1]*g[x+1])
return true;
else return false;
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
char ch;
char st[1000005];
getchar();
len=0;
for (int i=1;i<=n;++i)
{
ch=getchar();
st[++len]=ch;
if (i<n) st[++len]='#';
}
g[0]=1;
f[0].c=f[0].f=f[0].k=0;
for (int i=1;i<=len;++i)
{
f[i]=f[i-1];
if (st[i]=='c') f[i].c++;
if (st[i]=='f') f[i].f++;
if (st[i]=='k') f[i].k++;
g[i]=g[i-1]*131ll;
}
hash_head[0]=0;
hash_tail[len+1]=0;
for (int i=1;i<=len+1;++i)
{
hash_head[i]=hash_head[i-1]*131+st[i];
}
for (int i=len;i>=1;i--)
{
hash_tail[i]=hash_tail[i+1]*131+st[i];
}
ansc=0; ansf=0; ansk=0;
for (int i=1;i<=len;++i)
{
int l,r,mid;
l=0; r=len-i+1; mid=0;
while (l+1<r)
{
mid=(l+r)>>1;
if (check(mid,i)) l=mid; else r=mid;
}
ansc+=f[i+l].c-f[i-1].c;
ansf+=f[i+l].f-f[i-1].f;
ansk+=f[i+l].k-f[i-1].k;
}
printf("%lld %lld %lld\n",ansk,ansf,ansc);
for (int i=0;i<=len+2;++i)
{
f[i].c=f[i].f=f[i].k=0;
hash_head[i]=hash_tail[i]=0;
g[i]=0;
}
}
return 0;
}
H-Cutting Papers
用几何画板画出来的东西大概就是圆+矩形的东西。直接求面积。
#include<bits/stdc++.h>
using namespace std;
double PI=3.1415926;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
double k=n;
printf("%.10lf\n",
return 0;
}
I-Board Game
一开始多的一定随便摆 把k和多k分开考虑,最后枚举几个k 剩余一定均摊。
#include <bits/stdc++.h>
#define lls __int128
using namespace std;
lls read(){ lls x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void write(lls x){if(x>9) write(x/10);putchar(x%10+'0');}
typedef long long ll;
signed main ()
{
ll nn,mm,kk,xx;
while(scanf("%lld%lld%lld%lld",&nn,&mm,&kk,&xx))
{
lls n=nn;
lls m=mm;
lls k=kk;
lls x=xx;
if(k==1)
{
if(n*(n+1)/2>=x)
{
printf("YES ");
write(n*(n+1)/2);
printf("\n");
//printf("%lld\n",n*(n+1)/2);
}
else printf("NO\n");
break;
continue;
}
lls sum1=0;
lls t=0;
lls last=n;
if(n>m*k)
{
t=(n-m*k)/k;
last=n-t*k;
sum1+=(1ll+t)*t*k/2;
sum1+=last*t;
}
lls ans=0;
lls kk=0;
while(last>=0)
{
lls d=last/m;
lls mm=last%m;
lls tt=(1ll+mm)*mm*(d+1ll)+(m+mm+1)*(m-mm)*d;
tt/=2ll;
if(kk*last+tt+(1ll+kk)*kk*k/2>ans)
ans=kk*last+tt+(1ll+kk)*kk*k/2;
if(last<k)
break;
else {
last-=k;
kk++;
}
}
if(ans+sum1>=x)
{
printf("YES ");
write(ans+sum1);
printf("\n");
}
else puts("NO");
break;
}
return 0;
}
J-Check In
没人写的题。
K-Headphones
签到。
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,k;
void Solve(){
cin>>n>>k;
int lf=2*n-2*k,ans=lf/2+k+1;
if(ans+2*k>2*n) cout<<"-1\n";
else cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(T--){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}