A:
题目大意:统计x的个数是不是总数一半,不是的话要变成一半所需改变次数以及改变后的序列
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
char c[220];
int n;
while(scanf("%d",&n)!=EOF)
{
cin>>c;
int sum=0;
for(int i=0;i<n;i++)
{
if(c[i]=='x')
sum++;
}
int cnt=0;
for(int i=0;i<n;i++)
{
if(sum<n/2)
{
for(int i=0;i<n;i++)
{
if(sum==n/2) break;
if(c[i]=='X')
{
c[i]='x';
sum++;
cnt++;
}
}
}
else if(sum>n/2)
{
for(int i=0;i<n;i++)
{
if(sum==n/2) break;
if(c[i]=='x')
{
c[i]='X';
sum--;
cnt++;
}
}
}
}
cout<<cnt<<endl;
cout<<c<<endl;
}
return 0;
}
题目大意:给出城市(0,0),给出n个坐标,起始人数s,每个坐标k个人, 每个坐标可以覆盖到半径为r的区域,r=sqrt(x*x+y*y)的区域,问最小的半径是多少,使得城市的总人数大于等于1000000;
贪心排序即可;
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
struct node
{
int x,y;
double r;
int num;
}data[1010];
int cmp(const node &a,const node &b)
{
return a.r<b.r;
}
int main()
{
int n,s;
while(cin>>n>>s)
{
for(int i=0;i<n;i++)
{
cin>>data[i].x>>data[i].y>>data[i].num;
data[i].r=sqrt(data[i].x*data[i].x+data[i].y*data[i].y);
}
sort(data,data+n,cmp);
for(int i=0;i<n;i++)
{
s+=data[i].num;
if(s>=1000000)
{
printf("%.7lf\n",data[i].r);
break;
}
}
if(s<1000000)
cout<<"-1"<<endl;
}
return 0;
}
题目大意:题意:给出n个整数p1~pn,求Q。公式如图,
表示x异或y,即x^y。
此处借鉴别人的,觉得简单易懂,很好
分析:设 为公式1,
为公式2.
因为异或运算满足交换律,
所以公式2 = p1^p2^……^pn^(1%1)^(1%2)^……(1%n)^(2%1)%(2%2)^……^(2%n)^……^(n%1)^(n%2)^……^(n%n)
=p1^p2^……^pn^(1%1)^(2%1)^……(n%1)^(1%2)^(2%2)^……^(n%2)^……^(1%n)%(2%n)^……^(n%n)
又因为对于任何一个正整数k,(1~n) % k 只会有0~(k-1)这k种结果,所以(1%k)、(2%k)……(n%k)是有规律的,也就是(1%k)^(2%k)^……^(n%k)是有规律的。
例如当n=15,k=7时,(1%k)、(2%k)……(n%k)的结果如下表所示。
1 | 2 | 3 | 4 | 5 | 6 | 0 |
1 | 2 | 3 | 4 | 5 | 6 | 0 |
1 |
|
|
|
|
|
|
根据异或原则,a^a=0,0^a=a; 所以图中红色两行异或结果为0。所以(1%7)^(2%7)^……^(15%7)=1;
又如当n=25,k=7时。(1%7)、(2%7)……(25%7)的结果如下表。
1 | 2 | 3 | 4 | 5 | 6 | 0 |
1 | 2 | 3 | 4 | 5 | 6 | 0 |
1 | 2 | 3 | 4 | 5 | 6 | 0 |
1 | 2 | 3 | 4 |
|
|
|
所以
(
1%7)^(2%7)^……^(25%7) = 5^6^0 = 3
因此,在处理这个问题时,可以用一个数组a保存1异或到n的结果,然后枚举k=1~n,求出余数为0~(k-1)的有多少个整行,最后把不足一整行的那部分计算进去就行了。
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=1e6+10;
int a[maxn];
int main()
{
a[0]=0;
for(int i=1;i<=maxn;i++)
a[i]=a[i-1]^i;
int n,k;
while(cin>>n)
{
int ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
ans^=k;
if((n/i)&1) ans^=a[i-1];
ans^=a[n%i];
}
cout<<ans<<endl;
}
return 0;
}
D:
题目大意:
给你一个N×M的矩阵,上面有数字,从大的到小的要花费td,从小的到大的要花费tu,大小一样花费tp
要你这一个顺时针的圈,使这个花费加起来最接近t,四个边都要>=3
解题思路:暴力,先处理四个方向,然后暴力枚举四个点
ps:abs做好自己写,不然容易TLE;
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
struct node
{
int l,r,d,u,v;
} data[310][310];
int fabs2(int x)
{
if(x<0) x=-x;
return x;
}
int main()
{
int t,n,m;
while(scanf("%d%d%d",&n,&m,&t)!=EOF)
{
int tp,tu,td;
scanf("%d%d%d",&tp,&tu,&td);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&data[i][j].v);
data[i][j].u=data[i][j].d=data[i][j].l=data[i][j].r=0;
}
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(i!=1)
{
if(data[i-1][j].v==data[i][j].v)
data[i][j].u=data[i-1][j].u+tp;
else if(data[i-1][j].v<data[i][j].v)
data[i][j].u=data[i-1][j].u+tu;
else
data[i][j].u=data[i-1][j].u+td;
}
if(i!=1)
{
if(data[i-1][j].v==data[i][j].v)
data[i][j].d=data[i-1][j].d+tp;
else if(data[i-1][j].v>data[i][j].v)
data[i][j].d=data[i-1][j].d+tu;
else
data[i][j].d=data[i-1][j].d+td;
}
if(j!=1)
{
if(data[i][j-1].v==data[i][j].v)
data[i][j].l=data[i][j-1].l+tp;
else if(data[i][j-1].v<data[i][j].v)
data[i][j].l=data[i][j-1].l+tu;
else
data[i][j].l=data[i][j-1].l+td;
}
if(j!=1)
{
if(data[i][j-1].v==data[i][j].v)
data[i][j].r=data[i][j-1].r+tp;
else if(data[i][j-1].v<data[i][j].v)
data[i][j].r=data[i][j-1].r+td;
else
data[i][j].r=data[i][j-1].r+tu;
}
}
}
int x1,x2,y1,y2;
int ans=2000000000;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
for(int ii=i+2; ii<=n; ii++)
{
for(int jj=j+2; jj<=m; jj++)
{
int tmp=fabs2(t-(data[i][jj].l-data[i][j].l+data[ii][jj].r-data[ii][j].r+data[ii][jj].u-data[i][jj].u+data[ii][j].d-data[i][j].d));
if(ans>tmp)
{
ans=tmp;
x1=i;
y1=j;
x2=ii;
y2=jj;
}
}
}
}
}
printf("%d %d %d %d\n",x1,y1,x2,y2);
}
return 0;
}