比赛链接
题意:给你一串字符,它满足没有前导0,并且这个字符串由‘0’,‘1’组成(只有0或者1也行),这样的字符串称为正确的,现在我们可以做这两种操作,1:交换任意一对相邻的字符(“101” → “110”)2.两个‘1’可以合成为一个‘1’如(“110” → “10”)。
解法:找规律,如果没有‘1’的直接输出字符串就可以,其他的情况写几组可以发现,不管有奇数个‘1’还是偶数个,最终操作完之后就只有一个‘1‘且可以移动到最左端。
代码:
#include
#include
using namespace std;
int main()
{
int n;
char a[101];
cin>>n;
scanf("%s",a);
int ans=0,k,m,w=0;
for(int i=0;i<n;i++)
{
if(a[i]=='1')
ans++;
else
w++;
}
if(ans==0)
cout<<a;
else {
cout<<'1';
for(int j=1;j<=w;j++)
cout<<'0';
printf("\n");
}
}
题意:给你几个一维线段的左右端点,线段的序号为1~n,你只需要找到其中的一组线段i,j(1<=i,j<=n),满足得线段ai位于线段aj内。
部分[l1, r1]位于部分[l2, r2] 的要求是l1 ≥ l2和r1 ≤ r2.
解法:定义一个结构体包含左端点、有端点、对应的序号(不然排序之后不知道对应的是谁了)然后再定义快排规则,如果左端点不等的话则按左端点从小到大排(因为左端点越小它包的范围越大),反之则按右端点从大到小排,然后a[i-1]的左端点一定满足小于等于a[i]的左端点,如果再满足a[i-1]的右端点大于等于a[i]的则a[i]一定位于线段a[i-1]内(这一块是问的王锐,我写的判断的代码老错,有空再查一查哪错了)
代码:
#include
#include
#include
using namespace std;
struct p{
int x;
int y;
int q;//是用来记录对应的是哪个线段的
}a[300010];
bool cmp(p q,p w)
{
if(q.x!=w.x)
return q.x<w.x;
else
return q.y>w.y;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
a[i].q=i;
}
sort(a+1,a+1+n,cmp);
int i;
for(int i=2;i<=n;i++){
if(a[i].y<=a[i-1].y){
cout<<a[i].q<<' '<<a[i-1].q;
return 0;//它就直接代表程序结束了,不往下走了
}
}
cout<<-1<<' '<<-1;
}
错误的代码:
#include
#include
#include
using namespace std;
struct p{
int x;
int y;
int q;
}a[300010];
bool cmp(p q,p w)
{
if(q.x!=w.x)
return q.x<w.x;
else
return q.y>w.y;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
a[i].q=i;
}
sort(a+1,a+1+n,cmp);
int index=1,m=0;//这一块往下有问题
while(index!=n){
int i;
for( i=1;i<=n;i++)
{
if(a[index].y>=a[i].y&&a[index].x<=a[i].x){
if(index!=i){
cout<<a[i].q<<' '<<a[index].q;
m=1;
break;
}
else
continue;
}
}
if(i!=n)
break;
else
index++;
}
if(m==0)
cout<<-1<<' '<<-1;
}
题意:给你n行m列,还有一个步数k,一个人从(1,1)开始,问你m步后他走到哪里(0<=k
解法:就根据给出的已知条件的4行3列找规律,因为从(1,1)开始的,所以往下走(n-1)步会走到头,所以如果k<=n-1会按直线往下走,再往后找规律的话发现不好找,我们让他再接着往右走一步,即正好到了(n,2)即(k=n)这又是一种情况,其他情况就是(k>n)就有规律了(此时这个人是从(n,2)为起点开始的),设a=(k-n)%(m-1),b=(k-n)/(m-1),,这时可以发现如果(k-n)/(m-1)为偶数,那么她会往上走b步并且往纵坐标向右移动a步,最终就是(n-b,2+a),若为奇数则横坐标同理还是上移b步,纵坐标从m开始向左移动a步,最终就是(n-b,m-a)
代码:
#include
#include
using namespace std;
int main()
{
long long n,m,k;
cin>>n>>m>>k;
if(k<=n-1)
cout<<1+k<<' '<<1;
else if(k==n)
cout<<n<<' '<<2;
else if(k>n)
{
long long a,b;
a=(k-n)%(m-1);
b=(k-n)/(m-1);
if(b%2==0)
cout<<n-b<<' '<<2+a;
else
cout<<n-b<<' '<<m-a;
}}
题意:就是找公因数个数
代码:
#include
#include
using namespace std;
int main()
{
int n,i,sum=0;
cin>>n;
for(i=1;i<n;i++)
{
if(n%i==0)
sum++;
}
printf("%d\n",sum);
}
题意:就是一个人从原点(0,0)开始走,每次可以往上走一步或者往右走一步,只要他走过y=x这个边界则要付一枚银币。
解法:一开始我想记录每个点的横纵坐标然后通过纵坐标与横坐标比值是否大于一来判断,正解是先判断是否走到边界,然后如果到边界的这次走法与一下步的走法相同,那么一定走过边间,若走法不同则一定过不了边界。
代码:
#include
#include
using namespace std;
int main()
{
int n,sum=0,x=0,y=0;
char s[100010];
cin>>n;
getchar();
scanf("%s",s);
for(int i=0;i<n;i++)
{
if(s[i]=='U')
y++;
else
x++;
if(x==y&&s[i]==s[i+1])
sum++;
}
printf("%d\n",sum);
}
题意:要从大圆中找到找一个小圆使某一个点不在小圆中而且大圆未被小圆包含的面积最小,求这个小圆的圆心,为此我们要分情况:
1.点在圆外,那么直接让小圆的圆心等于大圆的,两个圆重合即可。
2.点在圆内且该点与大圆圆心重合,那么画画图可知,极限就是在大圆内找一个半径为2/R的与大圆内切的小圆即可
3.点在园内且点不与大圆圆心重合,比较麻烦用到了相似什么的,我是看了一个大佬的做法链接附上链接在此
我们很容易就可以得到r1=sqrt((x1-x2)(x1-x2)+(y1-y2)(y1-y2));
然后通过相似三角形我们可以得到r1/((R+r1)/2)=(x2-x1)/(x2-x)=(y2-y1)/(y2-y);
最后稍微化简就可以直接得到(x,y).半径的话就只需要(r1+R)/2就行了。
代码:
#include
#include
#include
using namespace std;
int main()
{
double R,x1,x2,y1,y2;
scanf("%lf%lf%lf%lf%lf",&R,&x1,&y1,&x2,&y2);
double r1=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
if(r1>R)
{
printf("%.10f %.10f %.10f\n",x1,y1,R);
return 0;
}
if(x1==x2 && y1==y2)
{
printf("%.10f %.10f %.10f\n",x1+0.5*R,y1,0.5*R);
return 0;
}
double x=(R+r1)/(r1*2);
printf("%.10f %.10f %.10f\n",x2-(x2-x1)*x,y2-(y2-y1)*x,(R+r1)/2);
return 0;
}