A-Red-Blue Shuffle
水题,速切。
比一比红比蓝大的个数和蓝比红大的个数,大的那个概率大。
#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
using namespace std;
char r[1010],b[1010];
int main()
{
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
scanf("%s%s",r,b);
int cntr=0,cntb=0;
for(int i=0;i<n;i++){
if(r[i]>b[i]) cntr++;
else if(r[i]<b[i]) cntb++;
}
if(cntr>cntb) puts("RED");
else if(cntr<cntb) puts("BLUE");
else puts("EQUAL");
}
}
B-Move and Turn
应当面壁思过,考场上为什么卡了那么久,捶了dfs还找不出规律。
这里说明一下,本题我不是找规律过的,是真的想出了做法。
先考虑一个问题,我第一步确定之后,之后沿x轴走和沿y轴走的步数是固定的。
于是我就先考虑点在横坐标上的移动,每一步相当于是+1或者-1,也就是说给定了步数(比如说a步),每一步可以+1或者-1,求最终可以到达的数是多少,很容易可以发现,最左到达a,最右是-a。把每个+1换成-1会使最终的点向左移动2格,因此最终能到达的不同格子是:
(
a
−
(
−
a
)
)
/
2
+
1
=
a
+
1
(a-(-a))/2+1=a+1
(a−(−a))/2+1=a+1
因此,对于确定的步数,可以得出在x轴上的不同终点数。同理y轴也可以同样的方法得出。
于是,如果第一步确定之后,就可以将两个轴上的终点个数一乘,就是平面中终点的个数了。
所以枚举第一步是沿x轴走还是y轴走。
最终答案时,如果n为奇数,那么先向x轴还是y轴是有区别的,此时恰好将两种答案错开。如果n为偶数,则哪个先走无所谓,所以答案会重合,要除以2。
#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
using namespace std;
ll getit(int x,int y){
ll xt,yt;
xt=x+1;yt=y+1;
return xt*yt;
}//在x轴上走x步,y轴上走y步时,平面中不同的终点数
int main()
{
int n;
scanf("%d",&n);
int x=(n+1)/2,y=n/2;//先走x
ll ans=0;
ans+=getit(x,y);
x=n/2,y=(n+1)/2;//先走y
ans+=getit(x,y);
if(n&1)
printf("%lld\n",ans);
else printf("%lld\n",ans/2);//若为偶数,则两次算的终点是重合的,除以2
}
C-Row GCD
我承认,考场上看到
1
0
18
\color{Red}{10^{18}}
1018就吓坏了。
其实很简单(就是坑多)。
考虑其特性,gcd中每一项都加上了一个相同的数,每次都重算是不现实的,因此,如果能预处理,那再好不过了。于是,gcd的性质中有一条能把加上的数刚好减去。
gcd
(
a
,
b
)
=
gcd
(
a
−
b
,
b
)
\gcd(a,b)=\gcd(a-b,b)
gcd(a,b)=gcd(a−b,b)
设g=gcd(a,b)
则ab可以表示为
a=x*g,b=y*g
则a-b=(x-y)*g
已知x与y互质,可得 x-y与y也互质(见下)
所以gcd(a-b,b)=g=gcd(a,b)
已知x与y互质,假设 x-y与y不互质
则有
x-y=a*k,y=b*k,k>1
所以,x=(a+b)*k
得gcd(x,y)=k>1,与条件不符
证明过程放在这里,便于越来越菜的我之后回来复习。
所以,对于式子
gcd
(
a
1
+
b
,
a
2
+
b
,
…
,
a
n
+
b
)
\gcd(a_1+b,a_2+b,\dots,a_n+b)
gcd(a1+b,a2+b,…,an+b)
可以将前两项拿出来看看,就是
gcd
(
a
1
+
1
,
a
2
+
1
)
=
gcd
(
a
1
−
a
2
,
a
2
+
1
)
\gcd(a_1+1,a_2+1)=\gcd(a_1-a_2,a_2+1)
gcd(a1+1,a2+1)=gcd(a1−a2,a2+1)
所以,整个式子就变成了如下的鸭子:
gcd
(
a
1
−
a
2
,
a
2
−
a
3
,
…
,
a
n
−
1
−
a
n
,
a
n
+
b
)
\gcd(a_1-a_2,a_2-a_3,\dots,a_{n-1}-a_n,a_n+b)
gcd(a1−a2,a2−a3,…,an−1−an,an+b)
所以对于每个b,只要先预处理出前面的一坨,就可以
O
(
l
o
g
1
e
18
)
O(log1e18)
O(log1e18),解决。
W
A
,
R
E
p
o
i
n
t
s
:
\color{Red}{WA,REpoints:}
WA,REpoints:
注意,要先将a从大到小
要特判n=1和前面的一坨gcd=0的情况。
#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
using namespace std;
const int MAXN=2e5+10;
ll gcd(ll x,ll y){return x%y==0?y:gcd(y,x%y);}
ll a[MAXN],b[MAXN];
bool cmp(ll x,ll y){return x>y;}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=m;i++) scanf("%lld",&b[i]);
sort(a+1,a+1+n,cmp);
ll gd=0;
for(int i=1;i<n;i++){
if(a[i]-a[i+1]==0) continue;//0不要参与gcd的运算,小心nan
if(gd==0) gd=a[i]-a[i+1];
gd=gcd(gd,a[i]-a[i+1]);
}
for(int i=1;i<=m;i++){
if(n==1||gd==0) printf("%lld ",a[n]+b[i]);
else printf("%lld ",gcd(gd,a[n]+b[i]));
}
}