A. Floor Number
题意:
有一栋楼,第一层有两个房间(编号 1 , 2 1,2 1,2),第二层有 x x x个房间(编号 3 , 4 , . . . , 2 + x 3,4,...,2+x 3,4,...,2+x),以后每一层也都是 x x x个房间,现在给你房间编号,输出它得楼层。
解题思路:
理解题意后直接做就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int main(){
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
int ans = 1+(n-2)/m;
if((n-2)%m)ans++;
if(n <= 2)ans=1;
cout<<ans<<endl;
}
return 0;
}
B. Symmetric Matrix
题意:
给你 n n n个 2 ∗ 2 2*2 2∗2得瓷砖(每格都有颜色),能否将 m ∗ m m*m m∗m的矩形都填上瓷砖,满足 s [ i ] [ j ] = s [ j ] [ i ] ( 1 ≤ i , j ≤ m , s [ i ] [ j ] 表 示 矩 形 i 行 j 列 的 颜 色 ) s[i][j]=s[j][i](1\leq i,j \leq m,s[i][j]表示矩形i行j列的颜色) s[i][j]=s[j][i](1≤i,j≤m,s[i][j]表示矩形i行j列的颜色)。
解题思路:
1、
m
m
m是奇数肯定不行。
2、当
m
m
m偶数,观察发现只要
2
∗
2
2*2
2∗2的瓷砖的左下角和右上角一样就可行。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int main(){
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
int f = 0;
for(int i=0;i<n;i++)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
if(b==c)
f=1;
}
if(m%2 || f==0)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
C. Increase and Copy
题意:
有个数组
a
a
a,开始只有一个元素
a
[
0
]
=
1
a[0]=1
a[0]=1,每次操作你可以选择以下之一:
1、选择数组中的一个元素
+
1
+1
+1。
2、复制数组中的一个元素到数组末尾。
现在要让数组中的元素和为
n
n
n,至少需要几次操作?
解题思路:
如果我们考虑 x x x次操作能得到的最大数组和,如果既有操作1,又有操作2,那么一定先执行所有操作1,之后再执行操作2。
当我们要得到的数组和为 n n n时,假设执行了 x 1 x1 x1次操作1,那么还需要执行操作2的次数是 ⌈ n x 1 ⌉ \lceil \frac{n}{x1} \rceil ⌈x1n⌉ ,当我打算枚举 x 1 x1 x1时想起高中的公式: a + b ≥ 2 ∗ a ∗ b a+b \geq 2*\sqrt{a*b} a+b≥2∗a∗b当 a = b a=b a=b时等号成立,,那么我只要让 x 1 x1 x1接近 n \sqrt{n} n就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int main(){
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
int c = sqrt(n);
if(c*c != n)
c++;
int d = n/c;
if(n%c)d++;
int ans = (c-1)+(d-1);
cout<<ans<<endl;
}
return 0;
}
D. Non-zero Segments
题意:
给你一个没有 0 0 0的数组,你要在其中插入尽量少的元素,让这个数组的子数字(连续的)的和都不为 0 0 0(你插入的这个数可以是很大的)
解题思路:
s u m [ i ] sum[i] sum[i]表示前 i i i个元素的前缀和,那么如果存在以 i i i结尾的子数组的和为 0 0 0,一定存在 s u m [ j ] = s u m [ i ] ( j < i ) sum[j]=sum[i](j < i) sum[j]=sum[i](j<i),我们可以用map记录已经出现过的前缀和,而且如果存在以 i i i结尾的子数组的和为 0 0 0的情况,我需要在 i i i前面插入一个数,我们插入一个“很大”的数,因为这样前面出现过的前缀和就没用了,我们需要清空下map。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
map<long long,int> mp;
int main(){
long long n,ans=0,sum=0;
mp[0]=1;
cin>>n;
for(int i=1;i<=n;i++)
{
long long a;
cin>>a;
sum += a;
if(mp[sum])
{
ans++;
mp.clear();
mp[0]=1;
sum = a;
}
mp[sum] = 1;
}
cout<<ans<<endl;
return 0;
}
E. Rock, Paper, Scissors
题意:
Alice和Bob猜拳,知道他们出石头剪刀布的次数,问Alice至少能赢几把和至多能赢几把。
解题思路:
1、最多能赢:就是Alice的石头能对上多少Bob的剪刀就对上,Alice的剪刀能对上多少Bob的布就对上,Alice的布能对上多少Bob的石头就对上,设Alice和Bob的石头剪刀布分别是
a
1
,
a
2
,
a
3
,
b
1
,
b
2
,
b
3
a1,a2,a3,b1,b2,b3
a1,a2,a3,b1,b2,b3,那么答案就是
m
i
n
(
a
1
,
b
2
)
+
m
i
n
(
a
2
,
b
3
)
+
m
i
n
(
a
3
,
b
1
)
min(a1,b2)+min(a2,b3)+min(a3,b1)
min(a1,b2)+min(a2,b3)+min(a3,b1)。
1、最少能赢:就是Alice的石头至少会对上多少Bob的剪刀,其实就是尽量让Alice的石头去对Bob石头和布,如果还有剩下那么就只能对剪刀,那么就是
m
a
x
(
0
,
(
a
1
−
(
b
1
+
b
3
)
)
)
max(0,(a1-(b1+b3)))
max(0,(a1−(b1+b3)))(剪刀、布同理)。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int main(){
int n,a1,a2,a3,b1,b2,b3;
cin>>n;
cin>>a1>>a2>>a3>>b1>>b2>>b3;
int ans2 = min(a1,b2)+min(a2,b3)+min(a3,b1);
int ans1 = 0;
ans1 += max(0,(a1-(b1+b3)));
ans1 += max(0,(a2-(b1+b2)));
ans1 += max(0,(a3-(b2+b3)));
cout<<ans1<<" "<<ans2<<endl;
return 0;
}
F. Number of Subsequences
题意:
有一个字符串只包含’a’、‘b’、‘c’、’?’,’?‘可以变成’a’、‘b’、‘c’中任意字符,问’?'变成的所有情况下(共有 3 x 3^x 3x种 x x x表示‘?’出现的次数),有多少个子串"abc"。具体看样例。
解题思路:
如果没有‘?’,那就简单了,和这题一样可以看下。如果当前是’?’:
1、那么已有的子串“a”的贡献(设
a
[
1
]
a[1]
a[1])个数要乘3,因为我不管填什么前面的
a
[
1
]
a[1]
a[1]都会有一遍贡献,之后还需要
a
[
1
]
+
+
a[1]++
a[1]++(这个’?‘我填’a‘)
2、已经有的子串“ab”的贡献(设
a
[
2
]
a[2]
a[2])个数要乘3,然后
a
[
2
]
+
=
a
[
1
]
a[2]+=a[1]
a[2]+=a[1]。
3、已经有的子串“abc”的贡献也就是答案(设
a
n
s
ans
ans)也要乘3,然后ans+=a[2]。
但是这样发现错了,原来是
a
[
1
]
a[1]
a[1]少算了,因为如果当前是“a”,它的贡献并不只是1,在这之前的所有’?‘我不管填什么这个’a’都会加贡献,所以还需要一个变量表示前面出现了几个’?’,那么当前’a’的贡献就是3*(’?‘的个数),那么就有了:
4、
a
[
0
]
∗
=
3
a[0]*=3
a[0]∗=3。
并且改正前面1、的
a
[
1
]
+
+
a[1]++
a[1]++为
a
[
1
]
+
=
a
[
0
]
a[1]+=a[0]
a[1]+=a[0]
当
s
[
i
]
s[i]
s[i]不等于’?'时思路差不多,只是不乘3变成相应的乘1,看代码。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
const int mod = 1e9+7;
char s[maxn];
long long n,a[5];
int main(){
long long ans=0;
cin>>n>>s;
memset(a,0,sizeof(a));
a[0]=1;
for(int i=0;i<n;i++)
{
if(s[i]=='a')
a[1]+=a[0];
else if(s[i]=='b')
a[2]+=a[1];
else if(s[i]=='c')
ans+=a[2];
else
{
ans*=3;
ans+=a[2];
a[2]*=3;
a[2]+=a[1];
a[1]*=3;
a[1]+=a[0];
a[0]*=3;
}
a[0]%=mod;a[1]%=mod;a[2]%=mod;
ans%=mod;
}
cout<<ans<<endl;
return 0;
}