题目描述
给定一个长度为 n 的数列 A1,A2,⋅⋅⋅,An 和一个非负整数 x,给定 m 次查询,每次询问能否从某个区间 [l,r] 中选择两个下标不同的数使得他们的异或等于 x。
输入格式
输入的第一行包含三个整数 n,m,x。
第二行包含 n 个整数 A1,A2,⋅⋅⋅,An。
接下来 m 行,每行包含两个整数 li,ri 表示询问区间 [li,ri]。
输出格式
对于每个询问,如果该区间内存在两个数的异或为 x 则输出 yes
,否则输出 no
。
数据范围
对于 20% 的评测用例,1 ≤ n,m ≤ 100
对于 40% 的评测用例,1 ≤ n,m ≤ 1000
对于所有评测用例,1 ≤ n,m ≤ 100000,0 ≤ x < 220,1 ≤ li ≤ ri ≤ n,0 ≤ Ai <220。
输入样例
4 4 1
1 2 3 4
1 4
1 2
2 3
3 3
输出样例
yes
no
yes
no
样例解释
显然整个数列中只有 2,3 的异或为 1。
具体实现
yes
,没有的话输出 no
。#include
using namespace std;
// 1<<20 表示2的20次方,+10是为了防止溢出
const int N = 100010, M = (1 << 20) + 10;
int n, m, x;
//last[M]表示每个数最后一次出现的位置
//g[N]表示用于表示 i 左边 f~i~ 的最大值
int last[M], g[N];
int main()
{
cin >> n >> m >> x;
for (int i = 1; i <= n; i ++ )
{
int a;
cin >> a;
//如果一个数字没有出现过,last数组是全局变量,就是0
//递归
g[i] = max(g[i - 1], last[a ^ x]);
//更新last
last[a] = i;
}
while (m -- )
{
int l, r;
cin >> l >> r;
if (g[r] >= l)
{
puts("yes");
}
else
{
puts("no");
}
}
system("pause");
return 0;
}
题目描述
给定 n 个整数 a1,a2,⋅⋅⋅,an,求它们两两相乘再相加的和,即
S=a1⋅a2+a1⋅a3+⋅⋅⋅+a1⋅an+a2⋅a3+⋅⋅⋅+an−2⋅an−1+an−2⋅an+an−1⋅an
输入格式
输入的第一行包含一个整数 n。
第二行包含 n 个整数 a1,a2,⋅⋅⋅,an。
输出格式
输出一个整数 S,表示所求的和。
请使用合适的数据类型进行运算。
数据范围
对于 30% 的数据,1 ≤ n ≤ 1000,1 ≤ ai ≤ 100。
对于所有评测用例,1 ≤ n ≤ 200000,1 ≤ ai ≤ 1000。
输入样例
4
1 3 6 9
输出样例
117
具体实现
#include
using namespace std;
const int N = 200010;
int n;
int a[N];
int main()
{
cin >> n;
long long sum = 0;
for(int i = 1; i <= n; i ++ )
{
cin >> a[i];
sum += a[i];
}
long long res = 0, cnt = 0;
for(int i = 1; i <= n; i ++ )
{
cnt += a[i];
res += a[i] * (sum - cnt);
}
cout << res << endl;
system("pause");
return 0;
}
题目描述
小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。
当两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,将数值小的排在前面。
例如,2022 排在 409 前面,因为 2022 的数位之和是 6,小于 409 的数位之和 13。
又如,6 排在 2022 前面,因为它们的数位之和相同,而 6 小于 2022。
给定正整数 n,m,请问对 1 到 n 采用这种方法排序时,排在第 m 个的元素是多少?
输入格式
输入第一行包含一个正整数 n。
第二行包含一个正整数 m。
输出格式
输出一行包含一个整数,表示答案。
数据范围
对于 30% 的评测用例,1 ≤ m ≤ n ≤ 300。
对于 50% 的评测用例,1 ≤ m ≤ n ≤ 1000。
对于所有评测用例,1 ≤ m ≤ n ≤ 106。
输入样例
13
5
输出样例
3
样例解释
1 到 13 的排序为:1,10,2,11,3,12,4,13,5,6,7,8,9。
第 5 个数为 3。
具体实现
#include
using namespace std;
const int N = 1000010;
int n, m;
int w[N], s[N];
bool cmp(int a, int b)
{
if (s[a] != s[b])
{
return s[a] < s[b];
}
return a < b;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
w[i] = i;
for (int j = i; j != 0; j /= 10)
{
s[i] += j % 10;
}
}
sort(w + 1, w + n + 1, cmp);
cout << w[m] << endl;
system("pause");
return 0;
}
题目描述
给定一个数组 A 和一些查询 Li,Ri,求数组中第 Li 至第 Ri 个元素之和。
小蓝觉得这个问题很无聊,于是他想重新排列一下数组,使得最终每个查询结果的和尽可能地大。
小蓝想知道相比原数组,所有查询结果的总和最多可以增加多少?
输入格式
输入第一行包含一个整数 n。
第二行包含 n 个整数 A1,A2,⋅⋅⋅,An,相邻两个整数之间用一个空格分隔。
第三行包含一个整数 m 表示查询的数目。
接下来 m 行,每行包含两个整数 Li、Ri,相邻两个整数之间用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。
数据范围
对于 30% 的评测用例,n,m ≤ 50;
对于 50% 的评测用例,n,m ≤ 500;
对于 70% 的评测用例,n,m ≤ 5000;
对于所有评测用例,1 ≤ n,m ≤ 105,1 ≤ Ai ≤ 106,1 ≤ Li ≤ Ri ≤ n。
输入样例
5
1 2 3 4 5
2
1 3
2 5
输出样例
4
样例解释
原来的和为 6+14=20,重新排列为 (1,4,5,2,3) 后和为 10+14=24,增加了 4。
具体实现
#include
using namespace std;
typedef long long LL;
const int N = 100010;
int n, m;
//w[N]表示原数组
//s[N]表示记录被加次数的数组
int w[N], s[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> w[i];
}
cin >> m;
while (m -- )
{
int l, r;
cin >> l >> r;
s[l] ++, s[r + 1] -- ;
}
//对原数组求前缀和
for (int i = 1; i <= n; i ++ )
{
s[i] += s[i - 1];
}
//最初的总和
LL sum1 = 0;
for (int i = 1; i <= n; i ++ )
{
sum1 += (LL)s[i] * w[i];
}
//重新排序后的总和
LL sum2 = 0;
sort(s + 1, s + n + 1);
sort(w + 1, w + n + 1);
for (int i = 1; i <= n; i ++ )
{
sum2 += (LL)s[i] * w[i];
}
cout << sum2 - sum1 << endl;
system("pause");
return 0;
}
题目描述
在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm×841mm,将 A0 纸沿长边对折后为 A1 纸,大小为 841mm×594mm,在对折的过程中长度直接取下整(实际裁剪时可能有损耗)。
将 A1 纸沿长边对折后为 A2 纸,依此类推。
输入纸张的名称,请输出纸张的大小。
输入格式
输入一行包含一个字符串表示纸张的名称,该名称一定是 A0、A1、A2、A3、A4、A5、A6、A7、A8、A9 之一。
输出格式
输出两行,每行包含一个整数,依次表示长边和短边的长度。
输入样例 1
A0
输出样例 1
1189
841
输入样例 2
A1
输出样例 2
841
594
具体实现
#include
using namespace std;
int main()
{
int n;
char s;
cin >> s >> n;
int x = 1189, y = 841;
while (n -- )
{
x /= 2;
if (x < y)
{
swap(x, y);
}
}
cout << x << endl << y << endl;
system("pause");
return 0;
}