在写这篇题解的时候其实现场赛都打完了,不过因为最近事比较多,一直没有写这篇题解。今天碰巧有空,又补了一波题(虽说最后还是没AK),下面进入正文~
-------------------------------------------------------------------------------------------------------------------------------
A题
大水题,直接贴代码
#include<cstdio> using namespace std; int main() { int n; int c; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&c); printf("%d\n",c*(c-1)/2); } return 0; }
B题
水题,用gcd做即可
#include<cstdio> using namespace std; int gcd(int a,int b) { int maxn,minn; if(a>=b) { maxn=a; minn=b; } else { maxn=b; minn=a; } int t; while(minn) { t=maxn%minn; maxn=minn; minn=t; } return maxn; } int main() { int a,b; while(scanf("%d%d",&a,&b)!=EOF) { printf("%d\n",gcd(a,b)); } return 0; }
C题
貌似使用前缀和做的,做了挺长时间了,有些忘了(逃)
#include<cstdio> #include<algorithm> using namespace std; long long int a[100010]; long long int back[100010]; int main() { long long int n,m; long long int sum; long long int index; while(scanf("%lld%lld",&n,&m)!=EOF) { sum=0; for(long long int i=0;i<n;i++) scanf("%lld",&a[i]); sort(a,a+n); if(n==1) printf("%lld\n",a[0]+m); else { for(long long int i=n/2;i<n;i++) { sum+=a[i]; back[i]=sum; } long long int u=(n+1)/2; for(long long int i=n-1;i>=n/2;i--) { if(u*a[i]-back[i]<=m) { index=i; m-=(u*a[i]-back[i]); for(long long int j=n/2;j<=i;j++) { a[j]=a[i]; } break; } u--; } long long int up=m/u; printf("%lld\n",a[index]+up); } } return 0; }
D题
找规律,但这个规律十分好找,打个表就出来了~
#include<cstdio> using namespace std; long long int f(long long int x) { if(x<=100) return f(f(x+11)); else return x-10; } int main() { int n; long long int t; scanf("%d",&n); while(n--) { scanf("%lld",&t); if(t<=100) printf("91\n"); else printf("%lld\n",t-10); } return 0; }
E题
我用的是bfs,这道题能过,但在现场赛一加强数据就被虐了(还是菜)~
#include<cstdio> #include<queue> using namespace std; typedef struct { int s; int na; int nb; } node; int bfs(int r) { node n1; n1.s=0; n1.na=1; n1.nb=1; queue<node> q; q.push(n1); while(!q.empty()) { node tem=q.front(); q.pop(); if(tem.nb==r) { return tem.s; } node n2; node n3; if(tem.na+tem.nb<=r) { n2.na=tem.na; n2.nb=tem.na+tem.nb; n2.s=tem.s+1; q.push(n2); } if(2*tem.nb<=r) { n3.na=tem.nb; n3.nb=2*tem.nb; n3.s=tem.s+1; q.push(n3); } } } int main() { int n; int t; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&t); printf("%d\n",bfs(t)); } return 0; }
F题
赛后补出来的题,推一下递推式+矩阵快速幂,不过我的矩阵快速幂给写慢了,用了900多毫秒才过。。。
#include<cstdio> #include<vector> using namespace std; typedef long long ll; ll M=1e9+7; typedef vector<ll> vec; typedef vector<vec> mat; mat mul(mat &A,mat &B) { int l1=A.size(); int l2=B[0].size(); int l3=B.size(); mat C(A.size(),vec(B[0].size())); for(int i=0;i<l1;i++) { for(int k=0;k<l3;k++) { for(int j=0;j<l2;j++) { C[i][j]=(C[i][j]+A[i][k]*B[k][j])%M; } } } return C; } mat powmod(mat A,ll n) { int l4=A.size(); mat B(l4, vec(l4)); for(int i=0;i<l4;i++) { B[i][i]=1; } while(n>0) { if(n&1) B=mul(B,A); A=mul(A,A); n>>=1; } return B; } int main() { ll n; while(scanf("%lld",&n)!=EOF) { mat A(3,vec(3)); A[0][0]=1; A[0][1]=1; A[0][2]=0; A[1][0]=-1; A[1][1]=0; A[1][2]=1; A[2][0]=1; A[2][1]=1; A[2][2]=1; A=powmod(A,n); ll t1; t1=(A[0][0]+A[0][2])%M; ll t2; t2=(A[1][0]+A[1][2])%M; ll ans; ans=(t1+t2)%M; if(ans<0) ans+=M; printf("%lld\n",ans); } return 0; }
G题
一道八数码问题,bfs+康拓展开来压缩状态即可~
#include<cstdio> #include<queue> #include<cstring> using namespace std; char biao[10]="012345678"; int bb[]={0,1,2,3,4,5,6,7,8}; char a[10]; int sx,sy; int st; int vis[370000]; int f[10] = {1,1,2,6,24,120,720,5040,40320,362880}; typedef struct { char c[10]; int cc[10]; int s; int z; int ct; } node; int Canton(int s[]) { int sun = 0, tmp; for (int i = 0; i < 9; i++) { tmp = 0; for (int j = i + 1; j < 9; j++) if (s[j] < s[i]) tmp++; sun += (tmp * f[9 - i - 1]); } return sun + 1; } int bfs() { queue<node> q; node n1; int dx[4]={1,-1,3,-3}; n1.s=0; n1.z=st; strcpy(n1.c,a); for(int i=0;i<9;i++) n1.cc[i]=n1.c[i]-'0'; n1.ct=Canton(n1.cc); vis[n1.ct]=1; q.push(n1); while(!q.empty()) { node tem=q.front(); q.pop(); if(strcmp(tem.c,biao)==0) return tem.s; // if(Canton(tem.cc)==Canton(bb)) // return tem.s; for(int i=0;i<4;i++) { if(tem.z%3==0&&i==1) continue; if(tem.z%3==2&&i==0) continue; node n2; n2.s=tem.s+1; int tx=tem.z+dx[i]; n2.z=tx; if(tx>=0&&tx<=8) { strcpy(n2.c,tem.c); char t=n2.c[tx]; n2.c[tx]=n2.c[tem.z]; n2.c[tem.z]=t; for(int i=0;i<9;i++) n2.cc[i]=n2.c[i]-'0'; int tt=Canton(n2.cc); if(vis[tt]==0) { q.push(n2); vis[tt]=1; } } } } return -1; } int main() { int n; int t; scanf("%d",&n); for(int i=1;i<=n;i++) { int u=0; memset(vis,0,sizeof(vis)); for(int j=1;j<=3;j++) { for(int k=1;k<=3;k++) { scanf("%d",&t); a[u]=t+'0'; if(t==0) st=u; u++; } } a[9]='\0'; int res=bfs(); if(res!=-1) printf("%d\n",res); else { printf("cannot\n"); } } return 0; }
H题
其实这是一道贪心题(证明的话不太容易),不过仔细想一想其实可以想出来~
就是排序,相邻的一定斜率最小,见代码:
#include<cstdio> #include<algorithm> #include<cmath> #include<vector> #include<cstdlib> #include<queue> #include<cstring> using namespace std; typedef struct { int w; int no; } P; P p[1000010]; bool cmp(P a,P b) { return a.w<b.w; } int main() { int n; int t; while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;i++) { scanf("%d",&t); p[i].w=t; p[i].no=i; } sort(p,p+n,cmp); double tem; double minn=2e9; for(int i=1;i<n;i++) { tem=fabs((double)(p[i].w-p[i-1].w)/(p[i].no-p[i-1].no)); minn=min(tem,minn); } printf("%.2lf\n",minn); } return 0; }
I题(不会,待补。。。)
J题
赛后写出来的题,用了一个Markov过程(其实我之前不知道。。。),简单地说就是未来的状态只与现在有关,而与过去无关。仔细想一想,这题确实是这样的。然后就是推个期望的递推式。。。详见代码:
#include<cstdio> #include<cmath> using namespace std; double e[510]; int t; double solve(int n) { double sum=0; for(int i=0;i<=500;i++) e[i]=0; e[0]=0; for(int i=1;i<=n;i++) { e[i]=(double)n/i; for(int j=1;j<=i;j++) { e[i]+=(1.0/i)*e[i%j]; } sum+=e[i]; } return sum/n+1; } int main() { while(scanf("%d",&t)!=EOF) printf("%.2lf\n",solve(t)); return 0; }最后附上xdoj上的题解(思路): http://acm.xidian.edu.cn/download/2018-online-unofficial-editorial.pdf