概述
上海市计算机学会2022年11月乙组解题报告
数对统计
题目描述
给定的
n
n
n 个数字
a
1
,
a
2
,
…
,
a
n
a_1,a_2,dots,a_n
a1,a2,…,an,你可以从中任选两个数字,并按其在原先序列中顺序组成一个新的数对。(即:当所选数对为
(
a
i
,
a
j
)
(a_i,a_j)
(ai,aj)时, 满足
i
<
j
i < j
i<j)
请问按此方法,能组成多少种本质不同的数对?
输入格式
输入第一行,一个正整数
输入第二行,
n
n
n个正整数
a
1
,
a
2
,
…
,
a
n
a_1,a_2,dots,a_n
a1,a2,…,an
输出格式
输出本质不同的数对个数
数据范围
∘
circ
∘ 对于
30
%
30%
30% 的数据,
1
≤
n
≤
10
1 leq n leq 10
1≤n≤10
∘
circ
∘ 对于
60
%
60%
60% 的数据,
1
≤
n
≤
1
0
3
1 leq n leq 10^3
1≤n≤103
∘
circ
∘ 对于
100
%
100%
100% 的数据,
1
≤
n
≤
1
0
5
1 leq n leq 10^5
1≤n≤105 且
1
≤
a
i
≤
n
1 leq a_i leq n
1≤ai≤n
样例数据
输入:
4
3 5 3 2
输出:
5
说明:
可以组出(3,5),(3,3),(3,2),(5,3),(5,2)共5对本质不同的数对
思路
用排列组合公式直接获取答案,然后用map映射各数对的数目将答案进行处理, O ( n 2 ) O(n^2) O(n2)初评可得60分
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int n , ans;
string s[MAXN];
map<string , int> mp;
map<string , int> mpp;
int main(){
string st = "";
cin >> n;
ans = n * (n - 1) / 2;
for(int i = 1; i <= n; ++i)
cin >> s[i];
for(int i = 1; i < n; ++i){
mp[s[i]]++;
if(mp[s[i]] != 1){
ans -= (n - i);
continue;
}
for(int j = i + 1; j <= n; ++j){
st = s[i] + " " + s[j];
if(mp[st] == 0)
mp[st]++;
else
ans--;
}
}
cout << ans << endl;
return 0;
}
思路二
∘
circ
∘ 用sum记录数组中不同数字的个数,在数组中扫一遍;
∘
circ
∘ 如果当前数字只有一个那么以这个数字为开始的数对就要减去一,若当前数字不止一个,则代表后面还有相同的数字而可以不用减去;
∘
circ
∘ 同时用哈希表来标记以这个相同数字为数对第一个数的有没有被记录过,没记录过答案就加上
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
long long n , sum , ans , a[MAXN] , b[MAXN];
bool vh[MAXN];
int main(){
memset(vh , false , sizeof(vh));
cin >> n;
for(int i = 1; i <= n; ++i){
cin >> a[i];
if(b[a[i]] == 0)
sum++;
b[a[i]]++;
}
for(int i = 1; i < n; ++i){
b[a[i]]--;
if(!b[a[i]]) sum--;
if(!vh[a[i]]){
ans += sum;
vh[a[i]] = true;
}
}
cout << ans << endl;
return 0;
}
思路三
将数依次扔到set里,对每个数统计一下前面set中元素个数
程序未实现
序列操作
题目描述
给定 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,dots,a_n a1,a2,…,an,一开始,所有数字都是 0 0 0,接下来将根据输入数据依次进行 q q q 条修改操作:
加法修改操作以字符 + 开头,后接两个整数
p
p
p 与
d
d
d,表示数列的第
p
p
p 项将增加
d
d
d;
乘法修改操作以字符 * 开头,后接一个整数
m
m
m,表示数列的每一项都将乘以
m
m
m。
请输出经过修改后数列,由于答案可能很大,输出每一个数字模
1
,
000
,
000
,
007
1,000,000,007
1,000,000,007 的余数。
输入格式
第一行:两个整数表示
n
n
n 与
q
q
q。
第二行到第
i
+
1
i+1
i+1 行:第
i
+
1
i + 1
i+1 行首先有一个字符表示操作类型,若是加法修改,后接两个整数
p
i
p_i
pi与
d
i
d_i
di ,若是乘法修改,后接一个整数
m
i
m_i
mi
输出格式
单独一行: n n n 个数字表示修改后每个数字模 1 , 000 , 000 , 007 1,000,000,007 1,000,000,007 的余数。
数据范围
∘
circ
∘ 对于
40
%
40%
40% 的数据,
n
,
q
≤
1000
n,qleq 1000
n,q≤1000
∘
circ
∘ 对于
80
%
80%
80% 的数据,
n
,
q
≤
50000
n,qleq 50000
n,q≤50000
∘
circ
∘ 对于
100
%
100%
100% 的数据,
n
,
q
≤
200
,
000
n,qleq 200,000
n,q≤200,000
∘
circ
∘
1
≤
d
i
,
m
i
≤
100
,
000
1 leq d_i, m_i leq 100,000
1≤di,mi≤100,000
样例数据
输入:
3 5
- 1 3
- 10
- 2 6
- 3 9
- 5
输出:
150 30 45
思路
直接暴力运算可得40分
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 10;
#define ll long long
const ll MOD = 1e9 + 7;
ll n , q;
ll a[MAXN];
int main(){
char ch;
ll p , d , m;
cin >> n >> q;
for(int i = 1; i <= q; ++i){
cin >> ch;
if(ch == '+'){
cin >> p >> d;
a[p] += d;
a[p] %= MOD;
}
else{
cin >> m;
for(int i = 1; i <= n; ++i)
a[i] *= m , a[i] %= MOD;
}
}
for(int i = 1; i < n; ++i)
cout << a[i] << " ";
cout << a[n] << endl;
return 0;
}
思路二
对于每个+ 和 * 进行维护 , 统计每次加上需要进行的*次数
代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
#define ll long long
const int d=1e9+7;
int n,q,a[MAXN],b[MAXN];
char op[MAXN];
ll ans[MAXN],g=1;//当前已经被乘上多少了
int main(){
cin>>n>>q;
for(int i=1;i<=q;++i){
cin>>op[i];
if(op[i]=='+')
cin>>a[i]>>b[i];
else
cin>>b[i];
}for(int i=q;i>=1;--i){
if(op[i]=='+')
ans[a[i]]=(ans[a[i]]+b[i]*g%d)%d;//加法运算,去掉取模即为(ans[a[i]]+b[i]*g),ans为被运算的数组
else
g=g*b[i]%d;//乘法对g操作
}for(int i=1;i<=n;++i)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}
最后
以上就是个性大船为你收集整理的上海市计算机学会2022年11月乙组解题报告上海市计算机学会2022年11月乙组解题报告数对统计序列操作的全部内容,希望文章能够帮你解决上海市计算机学会2022年11月乙组解题报告上海市计算机学会2022年11月乙组解题报告数对统计序列操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复