前言
新年快乐~
这次是我们精心为你们准备的题目,题目难度没有很难。周练的目的是为了在学到一点知识的同时也让寒假在家对编程不那么陌生。好好享受吧~。
A: abc-ABC
签到题,判断字符串是不是”abc“的的排列。两种解法
c++:
#include<bits/stdc++.h>
using namespace std;
int main() {
string s;
while(cin >> s){
sort(s.begin(), s.end());//使用sort函数进行排序
if (s == "abc")//如果字符串满足abc则输出abc
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}
c:
#include<bits/stdc++.h>
int a, b, c;
int main()
{
char s[4];
while(~ scanf("%s", s))
{
a=b=c=0;//注意初始化
for (int i = 0; i < 3; i++)
{
if (s[i] == 'a')//分别统计abc个数
a++;
if (s[i] == 'b')
b++;
if (s[i] == 'c')
c++;
}
if (a == 1 && b == 1 && c == 1)//如果各自都为1则输出Yes
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
B: 贴窗花
也是签到题,思路:破洞的坐标都知道,只要判断所有破洞的坐标都在圆内就可以。判断点在圆内方法:
(
x
−
a
)
2
+
(
y
−
b
)
2
<
=
r
2
(x-a)^{2}+(y-b)^{2}<=r^{2}
(x−a)2+(y−b)2<=r2
复杂度O(T*N)
#include<bits/stdc++.h>
using namespace std;
double A,B,R;
double jud(double a,double b)//判断是否超出圆
{
return (a-A)*(a-A)+(b-B)*(b-B)>R*R;
}
int main()
{
int t;cin>>t;
while(t--)
{
int n;
int temp=0;
scanf("%lf%lf%lf%d",&A,&B,&R,&n);
for(int i=0;i<n;i++)
{
double a,b;scanf("%lf%lf",&a,&b);
if(jud(a,b)) temp=1;
}
if(temp) printf("No\n");
else printf("Yes\n");
}
return 0;
}
C: 原来你也玩原神
还是签到题
可以直接模拟。复杂度O(N)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c;cin>>a>>b>>c;
int ans=a*20000+b*5000+c*1000;
for(int i=0;;i++)
{
if(i*(1250+750*i)/2>ans)
{
cout<<i<<endl;
break;
}
}
return 0;
}
当然,我们还可以用求根公式算:
化解我们可以得到:
375
x
2
+
625
x
−
a
n
s
=
0
375x^{2}+625x-ans=0
375x2+625x−ans=0
公式:
−
b
±
b
2
−
4
a
c
2
a
\frac{-b\pm \sqrt{b^{2}-4ac}}{2a}
2a−b±b2−4ac
复杂度O(1)
#include<bits/stdc++.h>
using namespace std;
int main()
{
double a,b,c;cin>>a>>b>>c;
double ans=a*20000+b*5000+c*1000;
cout<<(int)(sqrt(625*625+4*375*ans)-625)/(2*375)+1<<endl;
return 0;
}
D: 大小整数
依旧是签到题。
#include <iostream>
using namespace std;
int main()
{
int a, b, k;
cin >> a >> b >> k;
//从a开始,从小到大枚举,取b和第k位中间的最小值,防止数据不在范围内
for (int i = a; i <= min(b, a + k - 1); i++)
{
cout << i << endl;
}
//从小到大枚举,最大不超过b
for (int i = max(b - k + 1, a + k); i <= b; i++) //同理
{
cout << i << endl;
}
return 0;
}
E: a ^ b mod c
模板题,快速幂模板,复杂度log(N)。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll a, b, c;
cin >> a >> b >> c;
ll ans = 1;
while(b)
{
if(b & 1)
ans = (ans * a) % c;
a = a * a % c;
b /= 2;
}
cout << ans;
return 0;
}
F: 牛年大吉!犇犇犇!
本来应该是压轴题,暴力模拟应该是过不了的。数据问题没卡成。
模拟没啥好讲的,直接上代码:
复杂度O(
N
2
N^{2}
N2)
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ll N,A[200010],bi,sum=0;
int i,q,L,R,k;
scanf("%lld",&N);
for(i=1; i<=N; i++)
scanf("%lld",&A[i]);
scanf("%d",&q);
while(q--)
{
scanf("%d %d %lld",&L,&R,&bi);
for(i=L; i<=R; i++)
A[i]=A[i]+bi;
}
scanf("%d",&k);
while(k--)
{
sum=0;
scanf("%d %d",&L,&R);
for(i=L; i<=R; i++)
sum=sum+A[i];
printf("%lld\n",sum);
}
return 0;
}
O(
N
2
N^{2}
N2) 的复杂度2e5的数据数量级达到了10。在ACM中,1秒最多允许运行8的数量级。这题出题人数据的锅没卡成。(手动滑稽)正确的做法应该是前缀和加差分。
思路:首先用差分计算q次区间加。然后前缀和变为原数组,然后再一次前缀和。(注意,两次前缀和!)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=2e5+10;
ll a[N];
ll sum[N];//求前缀和
ll pre[N];//差分进行区间加减
int main()
{
int n,q,k;
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=n; i++)
{
pre[i]=a[i]-a[i-1];//差分
}
cin>>q;
int l,r,x;
for(int i=1; i<=q; i++)
{
cin>>l>>r>>x;
pre[l]+=x;
pre[r+1]-=x;//进行区间操作
}
for(int i=1; i<=n; i++)
{
pre[i]=pre[i]+pre[i-1];//还原数组
sum[i]=sum[i-1]+pre[i];//求前缀和
}
cin>>k;
for(int i=1; i<=k; i++)
{
cin>>l>>r;
printf("%lld\n",sum[r]-sum[l-1]);
}
return 0;
}