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;
}
后面的三道題還沒有做出來。