第一题 差分求和
题目描述
给定一个整数序列,对其中任意两个数,计算后项减前项的差,输出这些差的差。
例如对于 a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 a1,a2,a3,a4 来说,输出
( a 2 − a 1 ) − ( a 3 − a 1 ) − ( a 3 − a 2 ) − ( a 4 − a 1 ) − ( a 4 − a 2 ) − ( a 4 − a 3 ) (a_2-a_1)-(a_3-a_1)-(a_3-a_2)-(a_4-a_1)-(a_4-a_2)-(a_4-a_3) (a2−a1)−(a3−a1)−(a3−a2)−(a4−a1)−(a4−a2)−(a4−a3)
输入格式
第一行:单个整数 n n n
第二行: n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an
输出格式
单个整数表示结果
数据范围
对 50 % 50\% 50% 的数据, 1 ≤ n ≤ 500 , 1 ≤ a i ≤ 500 1≤n≤500,1≤a_i≤500 1≤n≤500,1≤ai≤500
对 50 % 50\% 50% 的数据, 1 ≤ n ≤ 500 , 000 , 1 ≤ a i ≤ 500 , 000 1≤n≤500,000,1≤a_i≤500,000 1≤n≤500,000,1≤ai≤500,000
样例数据
输入:
3
1 2 3
输出:
-2
分析1:暴推yyds!!!
对一些刚学过for循环的正好实用,但缺点就是两层嵌套,只有50分
代码1:50分
#include <bits/stdc++.h>
using namespace std;
long long n,a[500000];
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
}
long long ans=a[2]-a[1];//因为第一项总是(a2-a1),所以先算了
for(int i=3;i<=n;++i){//从第三个开始,不要担心n小于三,因为小于三就不执行了
for(int j=1;j<i;++j){
ans-=a[i]-a[j];//相减
}
}
cout<<ans << endl;
return 0;
}
分析2:偷袭!!!
O ( n 2 ) O(n^2) O(n2)效率太低了,只能有五十分,那只能采取偷袭的方法,出其不意!!!
用1,2,3三个数距离
根据上面的公式是:
( 2 − 1 ) − ( 3 − 1 ) − ( 3 − 2 ) = − 2 (2-1)-(3-1)-(3-2)=-2 (2−1)−(3−1)−(3−2)=−2
把公式拆开后:
2 − 1 − 3 + 1 − 3 + 2 2-1-3+1-3+2 2−1−3+1−3+2
简单排一下后:
2 − 1 + 1 + 2 − 3 − 3 2-1+1+2-3-3 2−1+1+2−3−3
看到了吗,除了原来的 2 − 1 2-1 2−1,还要加一下从二开始每个点的前缀和,然后再减去从三开始的每个数去乘当前i-1
可能有些同学认为是巧合,我们用题目开头的那个例子来实验:
原式:
( a 2 − a 1 ) − ( a 3 − a 1 ) − ( a 3 − a 2 ) − ( a 4 − a 1 ) − ( a 4 − a 2 ) − ( a 4 − a 3 ) (a_2-a_1)-(a_3-a_1)-(a_3-a_2)-(a_4-a_1)-(a_4-a_2)-(a_4-a_3) (a2−a1)−(a3−a1)−(a3−a2)−(a4−a1)−(a4−a2)−(a4−a3)
拆括号和排序:
a 2 − a 1 + a 1 + a 2 + a 1 + a 2 + a 3 − a 3 − a 3 − a 4 − a 4 − a 4 a_2-a_1+a_1+a_2+a_1+a_2+a_3-a_3-a_3-a_4-a_4-a_4 a2−a1+a1+a2+a1+a2+a3−a3−a3−a4−a4−a4
看到了吗,加上从二开始的每个点的前缀和,再减去从三开始的每个点成当前i减1
代码2:100分
#include<bits/stdc++.h>
using namespace std;
long long n,a[500010],vh[500010];
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
vh[i]=vh[i-1]+a[i];
}
long long ans=a[2]-a[1];
for(int i=2;i<n;++i) ans+=vh[i];
for(int i=3;i<=n;++i) ans-=a[i]*(i-1);
cout<< ans << endl;
return 0;
}
第二题 二进制异或
题目描述
给定两个只包含 0,1 的二进制数字,请你求出两个数字异或以后的二进制值是多少?(两个数字异或是指其二进制形式下按位做异或运算)
所谓异或,是指不同值异或结果为1,相同值异或结果为0,即:
0 ⊕ 0 = 0 0⊕0=0 0⊕0=0
0 ⊕ 1 = 1 0⊕1=1 0⊕1=1
1 ⊕ 0 = 1 1⊕0=1 1⊕0=1
1 ⊕ 1 = 0 1⊕1=0 1⊕1=0
输入格式
输入共两行,每行一个二进制数字
输出格式
输出共一行,一个二进制数字表示答案
数据范围
对于 50 % 50\% 50% 的数据,输入的二进制数字长度不超过7位
对于 100 % 100\% 100% 的数据,输入的二进制数字长度不超过100位
注意:输入的两个二进制数字长度可能不相同
样例数据
输入:
1101
1110
输出:
11
说明:
按位异或的答案为0011,去掉前导0后即为11
输入:
100101
1010
输出:
101111
分析:模拟
这题没啥好讲的,就是要注意在长短不一的情况下,要在短的前面补0,直到长度一致
代码:100分
#include <bits/stdc++.h>
using namespace std;
string a,b;
long long ans[110],k=0;
int main(){
cin>>a>>b;
if(a.size()>b.size()){//考试时为了稳妥使用的笨方法
long long f=a.size()-b.size();//a长度长时的解法
for(int i=0;i<f;++i){
ans[++k]=a[i]-'0';
}
for(int i=0;i<b.size();++i){
if(a[i+f]==b[i]){
ans[++k]=0;
}else{
ans[++k]=1;
}
}
}else if(a.size()<b.size()){//b长度长时的解法
long long f=b.size()-a.size();
for(int i=0;i<f;++i){
ans[++k]=b[i]-'0';
}
for(int i=0;i<a.size();++i){
if(b[i+f]==a[i]){
ans[++k]=0;
}else{
ans[++k]=1;
}
}
}else{//相同时的解法
for(int i=0;i<a.size();++i){
if(b[i]==a[i]){
ans[++k]=0;
}else{
ans[++k]=1;
}
}
}
bool f=true;
for(int i=1;i<=k;++i){
if(ans[i]==0){
if(f==false){
cout<< ans[i];
}
}else{
cout<< ans[i];
f=false;
}
}
return 0;
}
第三题 颜文字
题目描述
聊天对话中会用一些符号表示心情。 : − ) :-) :−) 表示好心情, : − ( :-( :−( 表示坏心情。给定一串字符序列表示用户的聊天记录,用户的心情指数定义为其中好心情数量减去坏心情数量。
请统计并输出用户的心情指数。
输入格式
一串字符表示聊天记录
输出格式
单个整数表示用户的心情指数
数据范围
设 n n n 表示输入序列的单词数量,则 1 ≤ n ≤ 10000 1≤n≤10000 1≤n≤10000
样例数据
输入:
are you ok? :-)
i am ok :-)
no :-( bad
输出:
1
分析:特性,哦不,机制解题
在C++中,有一个用法,叫:while(cin>>) 他有啥用呢?它是一段一段读的读到空格为一段,前面的颜文字前正好有个空格!!
代码:100分
#include <bits/stdc++.h>
using namespace std;
string s;
long long x,y;
int main(){
while(cin>>s){
if(s==":-)"){
x++;
}else if(s==":-("){
y++;
}
}
cout<< x-y << endl;
return 0;
}
第四题 选取子段(二)
题目描述
给定一个长度为 n n n的序列 a 1 , a 2 , . . . , a n a_1 ,a_2 ,...,a_n a1,a2,...,an ,请问多少种方案,能够从中选取一个连续段,使得该子段内所有元素的值都相同?
输入格式
输入共两行:
输入第一行,一个正整数 n n n
输入第二行, n n n个整数 a 1 , a 2 , . . . , a n a_1 ,a_2 ,...,a_n a1,a2,...,an
输出格式
输出一个整数,表示方案数。
数据范围
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 10 1≤n≤10 1≤n≤10
对于 60 % 60\% 60% 的数据, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1≤n≤103
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 , − 1 0 9 ≤ a i ≤ 1 0 9 1≤n≤10^5 , −10^9≤a_i ≤10 ^9 1≤n≤105,−109≤ai≤109
样例数据
输入:
5
3 1 1 2 5
输出:
6
说明:
每个元素单独成段均可,共{3},{1},{1},{2},{5}这5种方案
第2、3个元素组成的子段{1,1}也满足要求。
所以共6种方案
分析:这题没啥好讲的,主要就是要会怎么算一个连续相同的区间里有多少个符合要求的,有一个公式就是:个数*(个数-1)/2
还有就是要注意最后也要算一下,因为如果整个数列都相同的话,最后还没有算就退循环了,所以最后要算一下
代码:100分
#include <bits/stdc++.h>
using namespace std;
long long n,a[100010],ans=0,cnt=1;
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
}
long long f=a[1];
for(int i=2;i<=n;++i){
if(a[i]==f){
cnt++;
}else{
ans+=cnt*(cnt-1)/2;
cnt=1;
f=a[i];
}
}
ans+=cnt*(cnt-1)/2;
cout<< ans+n << endl;//因为每个单独的都可以作为一个,所以直接加n就行了
return 0;
}
第五题 观光单车
题目描述
已知公园内有出借观光单车,每辆单车限坐两人,且两人体重之和不能超过观光单车的限重 T T T。
小爱带领班级 n n n 位同学共同前往借车浏览风景,已知每位同学的体重分别为 w 1 , w 2 , , . . . , w n w_1,w_2, ,...,w_n w1,w2,,...,wn ,请问该班级最少借多少辆车,才能满足每个人的乘坐需求。
输入格式
输入共两行:
第一行,两个正整数 n , T n,T n,T
第二行, n n n个正整数 w 1 , w 2 , , . . . , w n w_1,w_2, ,...,w_n w1,w2,,...,wn
输出格式
输出一个正整数,表示最少租借单车的数量。
数据范围
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 10 1≤n≤10 1≤n≤10
对于 60 % 60\% 60% 的数据, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1≤n≤103
对于 100 100% 100 的数据, 1 ≤ n ≤ 1 0 5 , 1 ≤ w i ≤ T ≤ 1 0 4 1≤n≤10^5 ,1≤w_i≤T≤10^4 1≤n≤105,1≤wi≤T≤104
样例数据
输入:
7 50
15 41 32 42 27 25 19
输出:
5
分析:这题可以用贪心来写,首先先排完序,然后第一与最后比较,如果小于T,那就说明可以做一组,如果大于了,你想想,后面比这个还大,怎么比,说明只能单独做一辆车
代码:100分
#include<bits/stdc++.h>
using namespace std;
long long n,t,a[100010],ans=0;
int main(){
cin>>n>>t;
for(int i=1;i<=n;++i) cin>>a[i];
stable_sort(a+1,a+n+1);
long long l=1,r=n;
while(l<=r){
if(a[l]+a[r]<=t){//小于时
ans++,l++,r--;//一起移
}else{
ans++,r--;//当不一样时,大的单独一辆,往前移
}
}
cout<< ans << endl;
return 0;
}