======牛客多校第三场======
本场感觉还算比较满意吧,过了不少题。
=====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");
}
}