======牛客多校第三场====== 本场感觉还算比较满意吧,过了不少题。 =====A===== 很容易。适合作为第一学期程序设计的压轴题,或者算法课贪心算法中的水题。 #include int t,n; char s[2000005]; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); scanf("%s",s); int cnt1=0,ans=0; int i; for(i=0;i0) { ans++; cnt1--; } break; case'1': cnt1++; break; default: ans++; } } printf("%d\n",ans+cnt1/2); } return 0; } =====B===== 这个更容易,C语言程序设计课的难度。(ps:不会平衡树) #include char a[2000005]; int t,x,mod; int n=0; int main() { scanf("%s",a); scanf("%d",&t); mod=strlen(a); while(t--) { char op; scanf("%s",&op); scanf("%d",&x); if(op=='A') { int tmp=x+n; printf("%c\n",a[(tmp-1)%mod]); } else { n=(n+x+mod)%mod; } } return 0; } =====C===== 这个比较难。我队采用了8-10-6定位的方法,并计算了向量外积(矢量叉乘)来判定向哪边拐。 注意边界循环和eps。 #include #include double a[25][5]; double edge[25]; int t; int po6,po8,po106,po108; double A,B,C; double cal(int i,int j) { double tmp=sqrt((a[i][0]-a[j][0])*(a[i][0]-a[j][0])+(a[i][1]-a[j][1])*(a[i][1]-a[j][1])); return tmp; } int main() { scanf("%d",&t); while(t--) { int flag=1; int i; for(i=0;i<20;i++) { scanf("%lf%lf",&a[i][0],&a[i][1]); } for(i=0;i<20;i++) { edge[i]=cal(i,(i+1)%20); } for(i=0;i<20;i++) { if(fabs((edge[i] + edge[(i + 1) % 20] + edge[(i + 2) % 20]) - 23) < 0.01) { if(fabs(edge[i] - 6) < 0.01) { po6 = i; po106 = (i + 1) % 20; po108 = (i + 2) % 20; po8 = (i + 3) % 20; } else { po8 = i; po108 = (i + 1) % 20; po106 = (i + 2) % 20; po6 = (i + 3) % 20; } } } A = a[po108][1] - a[po106][1]; B = a[po106][0] - a[po108][0]; C = -(B * a[po106][1] + A * a[po106][0]); if(fabs(A) < 0.01) { if(a[po6][1] > a[po106][1]) { if(a[po6][0] < a[po8][0]) flag = 0; } else { if(a[po6][0] > a[po8][0]) flag = 0; } } else if (fabs(B) < 0.01) { if(a[po6][0] < a[po106][0]) { if(a[po6][1] < a[po8][1]) flag = 0; } else { if(a[po6][1] > a[po8][1]) flag = 0; } } else if(A * B > 0) { if(A < 0) { A = fabs(A); B = fabs(B); C = -C; } if(A * a[po6][0] + B * a[po6][1] + C > 0) { if(a[po106][1] > a[po108][1]) flag = 0; } else { if(a[po106][1] < a[po108][1]) flag = 0; } } else { if(B < 0) { B = fabs(B); A = -A; C = -C; } if(A * a[po6][0] + B * a[po6][1] + C > 0) { if(a[po106][1] < a[po108][1]) flag = 0; } else { if(a[po106][1] > a[po108][1]) flag = 0; } } if(flag) { printf("left\n"); } else { printf("right\n"); } } return 0; } =====E===== 动态规划。图论那里的思考略微难一些,参见任韩《图论》第四章(?忘了第几章)第一节“对集”部分,有完全相同的例题和细节证明,因此对于数学竞赛生应当是小菜一碟。至于动态规划的部分只是熟练活。 注意不要手误。方程敲错了谁也救不了(……)。 (适合作为算法课动态规划的压轴题之一——思维复杂度麻烦的类型) 另外,本题改成C代码的qsort貌似就过不了了,会RE,不知为何。 #include #include #include using namespace std; int a[200005]; int b[100005]; int c[100005]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int i; for(i=0;ic[i-1]?b[i-2]:c[i-1])+(a[2*i+4]-a[2*i+3]); c[i]=(b[i-1]>c[i-1]?b[i-1]:c[i-1]); } int mmm=(b[pmt]>c[pmt]?b[pmt]:c[pmt]); tmp-=mmm; printf("%lld\n",2*tmp); } } =====F===== 解一次不定方程题目。注意后面情况讨论以及调整为正数的操作。 #include char isprime[2000010]; int sq[2000010]; long long exgcd(long long a,long long b,long long *x,long long *y) { if(!b) { (*x)=1; (*y)=0; return a; } long long r=exgcd(b,a%b,&(*x),&(*y)),t=(*x); (*x)=(*y); (*y)=t-a/b*(*y); return r; } long long gcd(long long a,long long b) { return (b==0)?a:gcd(b,a%b); } char cal(long long a,long long b,long long c,long long *x,long long *y) { if(c%gcd(a,b)!=0) { return 0; } long long q=exgcd(a,b,&(*x),&(*y)); long long v=c/q; (*x)*=v; (*y)*=v; (*y)*=-1; return 1; } int main() { isprime[0]=isprime[1]=1; int i; sq[1]=1; for(i=2;i<=20000;i++) { if(!isprime[i]) { int j; for(j=i*i;j<=2000000;j+=i) { isprime[j]=1; } } if(i*i<=2000005) { sq[i*i]=i; } } for(i=1;i<2000005;i++) { if(!sq[i]) { sq[i]=sq[i-1]; } } int T; scanf("%d",&T); while(T--) { long long a,b; scanf("%lld%lld",&a,&b); if(b==1) { printf("-1 -1 -1 -1\n"); } else if(a%b==0) { int x=a/b; printf("%d 1 %d 1\n",x+1,1); } else if(!isprime[b]) { printf("-1 -1 -1 -1\n"); } else { int flag=1; long long l,r; for(l=2,r=sq[b]+2;l<=r+1;l++,r--) { if(l>=2&&l=2&&r =====L===== C语言优秀练习题。 #include char a[105]; int main() { scanf("%s",a); if((a[0]=='l'||a[0]=='L')&&(a[1]=='o'||a[1]=='O')&&(a[2]=='v'||a[2]=='V')&&(a[3]=='e'||a[3]=='E')&&(a[4]=='l'||a[4]=='L')&&(a[5]=='y'||a[5]=='Y')) { printf("lovely\n"); } else { printf("ugly\n"); } return 0; } =====G===== 以下是补题。 #include #include #include using namespace std; struct head { struct head *r; int val; }; int dsu[1000000]; int get(int v) { if (v == dsu[v]) return v; else return dsu[v] = get(dsu[v]); } pair g[1000000]; pair merge(pair a, pair b) { if (!a.second) return b; else { a.second->r = b.first; return make_pair(a.first, b.second); } } pair lst(int x) { struct head *t =(struct head*)malloc(sizeof(struct head)); t->r=0; t->val=x; return make_pair(t,t); } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); int i; for(i = 0; i < n; i++) { dsu[i] = i; g[i] =make_pair((struct head*)0,(struct head*)0); } for(i = 0; i < m; i++) { int x, y; scanf("%d%d",&x,&y); g[x] = merge(g[x], lst(y)); g[y] = merge(g[y], lst(x)); } int q; scanf("%d",&q); for(i = 0; i < q; i++) { int c; scanf("%d",&c); if (get(c) != c) { continue; } else { vector ord; struct head *s; for(s = g[c].first; s != 0; s = s->r) { int z = s->val; if (get(z) != c) { int who = get(z); dsu[who] = c; ord.push_back(who); } } g[c] =make_pair((struct head*)0,(struct head*)0); vector::iterator p; for(p=ord.begin();p!=ord.end();p++) { g[c] = merge(g[c],g[(*p)]); } } } for(i = 0; i < n; i++) { printf("%d ",get(i)); } printf("\n"); } }