A
只要每两个都不一样就可以,一旦出现两个一样的就改一个。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=2e5+5;
int n,ans;
char s[MAXN];int main()
{while(~scanf("%d",&n)){ans=0;scanf("%s",s);for(int i=0;i<n;i+=2){if(s[i]=='a'){if(s[i+1]=='a'){s[i+1]='b';ans++;}}else{if(s[i+1]=='b'){s[i+1]='a';ans++;}}}printf("%d\n%s\n",ans,s);}return 0;
}
B
就是一个排序
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e3+5;struct node
{int idx,p;
}a[MAXN];
int n;
int ans;bool cmp(const node&a,const node&b)
{return a.p>b.p;
}int main()
{while(~scanf("%d",&n)){ans=0;for(int i=1;i<=n;i++){a[i].idx=i;scanf("%d",&a[i].p);}sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){ans+=(i-1)*a[i].p+1;}printf("%d\n",ans);for(int i=1;i<n;i++){printf("%d ",a[i].idx);}printf("%d\n",a[n].idx);}return 0;
}
C
题目的意思很好理解,就是有点小繁琐。就是一张白纸两张黑纸,问黑纸会不会把白纸完全盖住。
这个问题我们不能直接暴力进行判断,我们首先要进行分析。
盖不住的情况有很多种,但是盖住的情况是可以分析的。如果一张黑纸直接将白纸全部盖住(四个角都盖住),那就没什么好说的了。
如果存在一个角没有被任何黑纸盖住,显然白纸是可以从上面看到的。
如果四个角都被黑纸盖住了,我们首先分析,每张黑纸只能盖住1,2,4个角,显然不能只盖住3个角。盖住四个角的我们已经判断过了,其中盖住一个角还能保证四个角都被黑纸盖住就说明另一张黑纸全部盖住了,如果不是全部盖住就是有角没有盖住,我们已经判断过了,那么剩下的只能是两张黑纸每张各占两个角,而且还是相对的两个角。
那么判断能否被覆盖的条件就很明了了:如果相对的这两张黑纸有交集(或者恰好拼在一起)就是可以盖住的,否则就是盖不住的。
分别进行判断。觉得可能是自己写复杂了。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e5+5;struct node
{int x,y;
}a[4];
int vis[4];int x1,x2,y1,y2;
int x3,x4,y3,y4;
int x5,x6,y5,y6;int main()
{while(~scanf("%d%d%d%d%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4,&x5,&y5,&x6,&y6)){if(x1>=x3 && y1>=y3 && x2<=x4 && y2<=y4 || x1>=x5 && y1>=y5 && x2<=x6 && y2<=y6){printf("NO\n");continue;}a[0].x=x1; a[0].y=y1;a[1].x=x1; a[1].y=y2;a[2].x=x2; a[2].y=y1;a[3].x=x2; a[3].y=y2;memset(vis,0,sizeof(vis));for(int i=0;i<4;i++){if(a[i].x>=x3 && a[i].y>=y3 && a[i].x<=x4 && a[i].y<=y4){vis[i]=1;}}for(int i=0;i<4;i++){if(a[i].x>=x5 && a[i].y>=y5 && a[i].x<=x6 && a[i].y<=y6){vis[i]=2;}}bool flag=true;for(int i=0;i<4;i++){if(!vis[i]){flag=false;break;}}if(!flag){printf("YES\n");}else{bool ok=false;if(vis[1]==vis[3]){if(vis[1]==1){if(y6>=y3)ok=true;}else{if(y4>=y5)ok=true;}}else{if(vis[1]==1){if(x4>=x5)ok=true;}else{if(x6>=x3)ok=true;}}if(ok){printf("NO\n");}else{printf("YES\n");}}}return 0;
}
D
我们用剩下最多的剑减去其他剩下的剑就可以得到至少拿走了多少剑。得到一个数列a1,a2,a3…an,这个数列里面肯定有一个是0,我们知道有一个结果肯定是t=gcd(a1,a2,a3…an),ans=a1/t+a2/t+a3/t+…+an/t。但是这个结果是不是最好的就不好说了,人家还可以每一个都多拿了一些,设为x,那么t=gcd(a1+x,a2+x,a3+x,…an+x),ans=(a1+x)/t+(a2+x)/t+…+(an+x)/t。x>=0。我们就在这些结果里面找最优解。
我们对这个结果进行观察,结合最大公因数的一个式子:gcd(a,b)=gcd(a,a-b),设mina=min(a1+x,a2+x,…,an+x),那么t=gcd(a1+x-mina,a2+x-mina,…an+x-mina),这就退化成了最开始的情形,所以说,最开始的情形是最优解。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=2e5+5;int n;
ll ans;
int a[MAXN],maxa;ll gcd(ll a,ll b)
{return b==0?a:gcd(b,a%b);
}int main()
{while(~scanf("%d",&n)){maxa=0; ans=0;for(int i=0;i<n;i++){scanf("%d",&a[i]);if(a[i]>maxa) maxa=a[i];}for(int i=0;i<n;i++){a[i]=maxa-a[i];}ll tmp=0;for(int i=0;i<n;i++){tmp=gcd(a[i],tmp);}for(int i=0;i<n;i++){ans+=a[i]/tmp;}printf("%lld %lld\n",ans,tmp);}return 0;
}
后面的三道题还没有做出来。