A题
暴力计算时间即可.
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> p; p operator +(const p &_,const p &__){ p ret; ret.second=(_.second+__.second); ret.first=(_.first+__.first+ret.second/60)%24; ret.second%=60; return ret; } int main(){ int t; scanf("%d",&t); while (t--){ p t=p(12,0); int x; scanf("%d",&x); t=t+p(0,x); if (t.second>=10) printf("%d:%d\n",t.first,t.second); else printf("%d:0%d\n",t.first,t.second); } }
B题
计算概率分类讨论.
首先路程大于等于2圈肯定不行
一圈以内及一圈概率计算一波
#include<bits/stdc++.h> using namespace std; int main(){ int t; scanf("%d",&t); while (t--){ int k,x; scanf("%d%d",&k,&x); if (k>=2*x) puts("0.00"); else if (k<x){ double in=1.*k/x,out=1-in; printf("%.2lf\n",in*in/2+in*out+out*in+out*out); } else{ double in=1.*(k-x)/x,out=1-in; printf("%.2lf\n",out*out/2); } } }
C题
二分答案,O(n)验证,小心边界问题
#include<bits/stdc++.h> using namespace std; const int N=100010; int n,a[N],num,b[N]; long long k; long long check(int x){ // cerr<<"x"<<x<<endl; int j=n; long long tot=0; num=0; for (int i=n; i>=1; --i){ if (a[i]>x) ++num; while (num>1&&j>i) num-=(a[j]>x),--j; tot+=j-i; // cerr<<"i j"<<i<<" "<<j<<" "<<num<<endl; } // cerr<<tot<<endl; return tot; } int main(){ int t; scanf("%d",&t); while (t--){ scanf("%d%lld",&n,&k); int ans=2333; for (int i=1; i<=n; ++i) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); for (int l=1,r=n,mid=(l+r)>>1; l<=r; mid=(l+r)>>1) if (1ll*n*(n-1)/2-check(b[mid])<k) ans=mid,r=mid-1; else l=mid+1; printf("%d\n",b[ans]); } }
D题
莫队算法(有信仰就能过)
#pragma GCC optimize(3) #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #include<bits/stdc++.h> using namespace std; typedef pair<int,int> p; const int N=100010; pair<p,int> a[N]; int n,m,s,q,an[N],num[N],fa[N],d[N]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } bool cmp(const pair<p,int> &_, const pair<p,int> &__){ return d[_.first.first]<d[__.first.first]||(d[_.first.first]==d[__.first.first]&&_.first.second<__.first.second); } int main(){ int t; scanf("%d",&t); for (int i=1; i<=100000; ++i) d[i]=i/1000; while (t--){ scanf("%d%d",&n,&m); for (int i=1; i<=n; ++i) fa[i]=i; for (int i=1; i<=m; ++i){ int x,y; scanf("%d%d",&x,&y); x=find(x); y=find(y); if (x==y) continue; fa[x]=y; } scanf("%d",&q); for (int i=1; i<=q; ++i) scanf("%d%d",&a[i].first.first,&a[i].first.second),a[i].second=i; for (int i=1; i<=n; ++i) num[i]=0; for (int i=1; i<=n; ++i) find(i); sort(a+1,a+q+1,cmp); int l=1,r=0,ans=0; for (int i=1; i<=q; ++i){ int ll=a[i].first.first,rr=a[i].first.second; while (r<rr){ ++r; if (!num[fa[r]]++) ++ans; } while (r>rr){ if (!--num[fa[r]]) --ans; --r; } while (l>ll){ --l; if (!num[fa[l]]++) ++ans; } while (l<ll){ if (!--num[fa[l]]) --ans; ++l; } an[a[i].second]=ans; } for (int i=1; i<=q; ++i) printf("%d\n",an[i]); } }
E题
OEIS大法好(待研究)
#include<bits/stdc++.h> using namespace std; int f[100]; int main(){ int t; scanf("%d",&t); f[1]=7; for (int i=2; i<=11; ++i) f[i]=f[i-1]*7/*,printf("%d\n",f[i])*/; while (t--){ int x; scanf("%d",&x); printf("%.0Lf\n",2*ceil((long double)sqrt(12ll*x-3))); } }
F题
貌似是一道codeforces原题,大佬讲过,未AC
G题
求树上某点出发最长链,再分类讨论.
#include<bits/stdc++.h> using namespace std; const int N=1000010; int ne[N<<1],fi[N],b[N<<1],k,dep[N],dis[N],n,q; void add(int x,int y){ ne[++k]=fi[x]; b[fi[x]=k]=y; } void dfs(int x,int fa,int deep){ dep[x]=deep; dis[x]=max(dis[x],deep); for (int j=fi[x]; j; j=ne[j]) if (b[j]!=fa) dfs(b[j],x,deep+1); } int main(){ int t; scanf("%d",&t); while (t--){ scanf("%d",&n); for (int i=1; i<=n; ++i) fi[i]=dep[i]=dis[i]=0; k=0; for (int i=1; i<n; ++i){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0,0); int mx=1; for (int i=2; i<=n; ++i) if (dep[i]>dep[mx]) mx=i; dep[mx]=0; dfs(mx,0,0); int mxx=1; for (int i=2; i<=n; ++i) if (dep[i]>dep[mxx]) mxx=i; dep[mxx]=0; dfs(mxx,0,0); scanf("%d",&q); for (int i=1; i<=q; ++i){ int x,y; scanf("%d%d",&x,&y); // cerr<<y-(n-dis[x]-1)*2<<" "<<dis[x]<<endl; if (dis[x]>=y){ printf("%d\n",y+1); // cerr<<"dis"<<dis[x]<<" "<<y<<endl; } else if (y<=(n-dis[x]-1)*2){ printf("%d\n",max(y/2+1,dis[x]+1)); // cerr<<"2t"<<endl; } else printf("%d\n",max(dis[x]+1,(n-dis[x]-1)+1+y-(n-dis[x]-1)*2)); } } }
H题
两次01背包
#include <bits/stdc++.h> using namespace std; const int INF=1e9+7; const int N=1010; int n,m,q; int a[N],b[N],c[N],d[N],f[N],g[N+N]; int main(){ int t; scanf("%d",&t); while (t--){ scanf("%d",&n); int suma=0; for (int i=1; i<=n; ++i) scanf("%d%d",&a[i],&b[i]),suma+=a[i]; scanf("%d",&m); for (int i=1; i<=m; ++i) scanf("%d%d",&c[i],&d[i]); scanf("%d",&q); for (int i=1; i<=1000; ++i) f[i]=INF; for (int i=1; i<=n; ++i) for (int j=1000; j>=b[i]; --j) f[j]=min(f[j-b[i]]+a[i],f[j]); for (int i=1; i<=2000; ++i) g[i]=0; for (int i=1; i<=m; ++i) for (int j=2000; j>=d[i]; --j) g[j]=max(g[j-d[i]]+c[i],g[j]); int ans=0; for (int i=0; i<=1000; ++i) ans=max(ans,suma-f[i]+g[i+q]); printf("%d\n",ans); } }
I题
毫无想法
看起来是压轴题.(待研究)
J题
贪心的代码不懂
不过可以用带权最小路径覆盖做.
#include <bits/stdc++.h> using namespace std; #define int long long typedef pair<long long,long long> p;//? const long double INF=1e11; const int N=210; struct edge{ int y,cap; long double cost; int op; edge(int y,int cap,long double cost,int op):y(y),cap(cap),cost(cost),op(op){} }; vector<edge> g[N<<1]; p prep[N<<1]; bool in[N<<1]; int a[N],b[N]; long double f[N<<1]; int n,m,s,t; long double spfa(){ queue<int> q; fill(f+s,f+t+1,INF); fill(in+s,in+t+1,0); f[s]=0; q.push(s); in[s]=1; while (!q.empty()){ int x=q.front(); q.pop(); in[x]=0; for (size_t j=0; j<g[x].size(); ++j){ edge e=g[x][j]; if (e.cap&&f[e.y]>f[x]+e.cost){ f[e.y]=f[x]+e.cost; prep[e.y]=p(x,j); if (!in[e.y]) q.push(e.y),in[e.y]=1; } } } if (f[t]>=0) return -1; int that=INF; for (int i=t; i!=s; i=prep[i].first) that=min(that,g[prep[i].first][prep[i].second].cap); for (int i=t; i!=s; i=prep[i].first){ edge &e=g[prep[i].first][prep[i].second]; e.cap-=that; g[e.y][e.op].cap+=that; } return that*f[t]; } bool init(int x,bool a,int y,bool b){ if (a==b) return x>=y; if (a) return x>=(y<<1); return ((x*x)<<1)>=y*y; } void add(int x,int y,int cap,long double cost){ g[x].push_back(edge(y,cap,cost,g[y].size())); g[y].push_back(edge(x,0,-cost,g[x].size()-1)); } void myunique(int *r,int &len){ sort(r+1,r+len+1); len=unique(r+1,r+len+1)-r-1; } signed main(){ int ttt; scanf("%lld",&ttt); while (ttt--){ scanf("%lld%lld",&n,&m); for (int i=1; i<=n; ++i) scanf("%lld",&a[i]); for (int i=1; i<=m; ++i) scanf("%lld",&b[i]); myunique(a,n); myunique(b,m); s=0; t=((n+m)<<1)+1; for (int i=s; i<=t; ++i) g[i].clear(); for (int i=1; i<=n; ++i) add(s,i,1,a[i]*a[i]); for (int i=1; i<=m; ++i) add(s,n+i,1,acos(-1)*b[i]*b[i]); for (int i=1; i<=n+m; ++i) add(i,n+m+i,1,-INF),add(n+m+i,t,1,0); for (int i=1; i<=n+m; ++i) for (int j=1; j<=n+m; ++j) if (i!=j&&init(i<=n?a[i]:b[i-n],i<=n,j<=n?a[j]:b[j-n],j<=n)) add(n+m+i,j,1,0); long double t,ans=0; while ((t=spfa())!=-1) ans+=t; printf("%.2Lf\n",ans+(n+m)*INF); } }
K题
仅有个位数的人过.不过我把另一个AC的叉掉了,我的复杂度为O(q*sqrt(n)*log(n))
此题数据范围有毒. a[i]<=n 不存在的.(p.s.此题暴力可以水过)
#pragma GCC optimize(3) #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #include <bits/stdc++.h> using namespace std; const int N=20010,NODE=2000010; vector<int> g[N]; struct node{int v,l,r;}T[NODE]; int ll,rr,sz,root[N],fi[N],ne[N<<1],b[N<<1],top[N],v[N],k,a[N],s,n,q,d; map<int,int> mp; void clear(){ for (int i=1; i<=n; ++i) fi[i]=0; for (int i=1; i<=n; ++i) g[i].clear(); mp.clear(); k=sz=d=0; } void add(int x,int y){ ne[++k]=fi[x]; b[fi[x]=k]=y; } void read(int &x){ char ch=getchar(); x=0; while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); } void init(){ read(n); s=(int(sqrt(n))>>1)+1; for (int i=1; i<n; ++i){ int x,y; read(x); read(y); add(x,y); add(y,x); } for (int i=1; i<=n; ++i) read(a[i]),mp[a[i]]=1; for (map<int,int>::iterator i=mp.begin(); i!=mp.end(); ++i) i->second=++d; for (int i=1; i<=n; ++i) g[a[i]=mp[a[i]]].push_back(i); } int ask(int ind,int l,int r){ if (!ind) return 0; if (ll<=l&&r<=rr) return T[ind].v; int mid=(l+r)>>1,ret=0; if (ll<=mid) ret+=ask(T[ind].l,l,mid); if (mid<rr) ret+=ask(T[ind].r,mid+1,r); return ret; } void fork(int &ind,int pa,int l,int r){ T[ind=++sz]=T[pa]; if (l==r) return void(++T[ind].v); int mid=(l+r)>>1; ll<=mid?fork(T[ind].l,T[pa].l,l,mid):fork(T[ind].r,T[pa].r,mid+1,r); T[ind].v=T[T[ind].l].v+T[T[ind].r].v; } void add(int &ind,int l,int r){ if (!ind) T[ind=++sz]=T[0]; if (l==r) return void(T[ind].v+=rr); int mid=(l+r)>>1; ll<=mid?add(T[ind].l,l,mid):add(T[ind].r,mid+1,r); T[ind].v=T[T[ind].l].v+T[T[ind].r].v; } void build(int x,int fa){ ll=a[x]; fork(root[x],root[fa],1,d); for (int j=fi[x]; j; j=ne[j]) if (b[j]!=fa) build(b[j],x); } void dfs(int x,int fa){ v[x]=(a[x]==rr); for (int j=fi[x]; j; j=ne[j]) if (b[j]!=fa){ dfs(b[j],x); v[x]+=v[b[j]]; } } void zig(int x){ top[x]=0; rr=x; dfs(1,0); for (int i=1; i<=n; ++i){ ll=a[i]; rr=v[i]; if (rr) add(top[x],1,d); } } void solve(){ build(1,0); for (int i=1; i<=d; ++i) if (g[i].size()>s) zig(i); read(q); while (q--){ int x,k,y; read(x); read(k); y=x; if (mp.find(x)==mp.end()){putchar('0'); putchar('\n'); continue;} x=mp[x]; ll=max(mp.lower_bound(y-k)->second,1); rr=min((--mp.upper_bound(y+k))->second,d); if (g[x].size()<=s){ int ans=0; for (size_t j=0; j<g[x].size(); ++j) ans+=ask(root[g[x][j]],1,d); printf("%d\n",ans-g[x].size()); } else printf("%d\n",ask(top[x],1,d)-g[x].size()); } } int main(){ int t; read(t); while (t--){ init(); solve(); clear(); } }
L题
我wa了好几发.负进制搞一搞.
#include<bits/stdc++.h> using namespace std; int st[100]; int calc(int x){ memset(st,0,sizeof(st)); int top=0; for (int i=1; i<=4; ++i){ st[++top]=x%9; x/=9; if (st[top]>=5){ st[top]=st[top]-9; ++x; } } int ans=0; for (int i=1; i<=4; ++i) ans+=abs(st[i]); return ans+x; } int main(){ int t; scanf("%d",&t); while (t--){ int x; scanf("%d",&x); int t=1; int z=1e9+7; printf("%d\n",calc(x)); } }