赞
踩
输出序列中出现最多次数的个数。
#include "bits/stdc++.h" using namespace std; map<int, int> mp; void solve() { int _; cin >> _; while(_--) { int n; cin >> n; mp.clear(); int ans = -1; for(int i = 1;i <= n; i++) { int x; cin >> x; mp[x]++; ans = max(ans, mp[x]); } cout << ans << endl; } } signed main() { solve(); }
题意:有一个luck数d,问能不能将一个x拆成任意多个数之和,并且每个数之中都要有一个d?
思路:
首先盲猜写
x
>
d
∗
10
x>d*10
x>d∗10都是可以的,因为都可以拆成10个数,每个数无非多加了很多个10而已。
所以打表
d
∗
10
d*10
d∗10之内的数即可,只需要判断尾部,尾部对了,并且小于x,无非就多加几个10而已。
#include "bits/stdc++.h" using namespace std; void solve() { int _; cin >> _; while(_--) { int q, d; cin >> q >> d; for(int i = 1;i <= q; i++) { int x; cin >> x; bool flag = false; if(x >= d * 10) flag = true; for(int j = 1;j <= 10; j++) { int t = j * d; if(t <= x && (t % 10 == x % 10)) { flag = true; break; } } cout << (flag ? "YES" : "NO") << endl; } } } signed main() { solve(); }
题意:给有 2 ∗ n 2*n 2∗n个数字的数组d,问能不能构造出一组“对称数组”(有一个整数a,必然有一个负数-a,0不行),并且一个数和其他所有数之差的绝对值之和都能在原数组找到。即 ∑ j = 1 n ∣ a i − a j ∣ = d 某 个 数 \sum_{j=1}^n|a_i-a_j|=d_{某个数} ∑j=1n∣ai−aj∣=d某个数。
思路:
因为是对称数组,所以原数组中的数必须有不同的n个偶数,奇数是不行的,因为
∑
j
=
1
n
∣
a
i
−
a
j
∣
\sum_{j=1}^n|a_i-a_j|
∑j=1n∣ai−aj∣得出来一定是个偶数。
加入我们设要构造的数组为
a
1
,
a
2
.
.
.
a
n
,
−
a
1
,
−
a
2
.
.
.
−
a
n
a_1,a_2...a_n,-a_1,-a_2...-a_n
a1,a2...an,−a1,−a2...−an,所以
∑
j
=
1
n
∣
a
i
−
a
j
∣
\sum_{j=1}^n|a_i-a_j|
∑j=1n∣ai−aj∣最小的数为
2
(
a
1
+
a
2
+
.
.
.
+
a
n
)
2(a_1+a_2+...+a_n)
2(a1+a2+...+an),这就是为什么一定要是偶数了,方便起见,将d数组每个数都除2判断一下,设
a
1
+
a
2
+
.
.
.
+
a
n
=
s
u
m
a_1+a_2+...+a_n=sum
a1+a2+...+an=sum那么我们可以得到所有的数:
(将d数组从小到大排序)
这样我们是看不出来什么样的,前后做一个差分可以得到:
s
u
m
=
d
[
1
]
sum=d[1]
sum=d[1]
a
2
−
a
1
=
d
[
2
]
−
d
[
1
]
a_2-a_1=d[2]-d[1]
a2−a1=d[2]−d[1]
2
(
a
3
−
a
2
)
=
d
[
3
]
−
d
[
2
]
2(a_3-a_2)=d[3]-d[2]
2(a3−a2)=d[3]−d[2]
3
(
a
4
−
a
3
)
=
d
[
4
]
−
d
[
3
]
3(a_4-a_3)=d[4]-d[3]
3(a4−a3)=d[4]−d[3]
…
(
n
−
1
)
(
a
n
−
a
n
−
1
)
=
d
[
n
]
−
d
[
n
−
1
]
(n-1)(a_n-a_{n-1})=d[n]-d[n-1]
(n−1)(an−an−1)=d[n]−d[n−1]
我们可以解这n个方程,得到a数组的n个正数,但不不好解它,我们先假设 a 1 = 1 ( 不 能 等 于 0 , 对 称 数 组 , 0 是 不 允 许 的 ) a_1=1(不能等于0,对称数组,0是不允许的) a1=1(不能等于0,对称数组,0是不允许的),然后解出所有的 a i a_i ai,最后算出 s u m sum sum是 a 1 + . . . + a n a_1+...+a_n a1+...+an。
a
2
=
d
[
2
]
−
d
[
1
]
+
a
1
a_2=d[2]-d[1]+a_1
a2=d[2]−d[1]+a1
a
3
=
d
[
3
]
−
d
[
2
]
2
+
a
2
a_3=\frac{d[3]-d[2]}{2}+a_2
a3=2d[3]−d[2]+a2
a
4
=
d
[
4
]
−
d
[
3
]
3
+
a
3
a_4=\frac{d[4]-d[3]}{3}+a_3
a4=3d[4]−d[3]+a3
…
a
n
=
d
[
n
]
−
d
[
n
−
1
]
n
−
1
+
a
n
−
1
a_n=\frac{d[n]-d[n-1]}{n-1}+a_{n-1}
an=n−1d[n]−d[n−1]+an−1
如何判断YES还是NO呢?
我们发现, a 1 a_1 a1每+1都会使所有数+1,即sum加了n,所以我们判断如果 s u m < = d [ 1 ] , 并 且 ( d [ 1 ] − s u m ] % n ) = = 0 , 输 出 Y E S , 反 之 N O 。 sum<=d[1],并且(d[1]-sum]\%n)==0,输出YES,反之NO。 sum<=d[1],并且(d[1]−sum]%n)==0,输出YES,反之NO。
#include "bits/stdc++.h" using namespace std; typedef long long ll; void solve() { int _; cin >> _; while(_--) { int n; cin >> n; vector<ll>v(n * 2); bool flag = true; for(int i = 0;i < n * 2; i++) { cin >> v[i]; if(v[i] & 1) flag = false; else v[i] /= 2; } if(!flag) { cout << "NO" << endl; continue; } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); if(v.size() != n) { cout << "NO" << endl; continue; } ll t = 1; ll sum = t; for(int i = 1;i < n; i++) { if((v[i] - v[i - 1]) % i == 0) { ll a = (v[i] - v[i - 1]) / i + t; sum += a; t = a; } else { flag = false; break; } } if(flag && (sum <= v[0] && (v[0] - sum) % n == 0)) { cout << "YES" << endl; } else { cout << "NO" << endl; } } } signed main() { solve(); }
题意:给n个数 x 1 , x 2 . . . x n x_1,x_2...x_n x1,x2...xn,从中选择两个数x和y,将 2 ∗ x − y 2*x-y 2∗x−y放入数组中,可以操作多次,问能不能得到一个k。
思路:
2
∗
x
−
y
=
x
+
x
−
y
2*x-y=x+x-y
2∗x−y=x+x−y,因为两个数一直辗转相减是可以得到这两个数的最大公因数,所以两个数的差即为最大公因数的倍数,所以为了每个数都可以被用到,我们先求出
n
−
1
n-1
n−1个差的
g
c
d
gcd
gcd,这样我们可以得到任意多个
g
c
d
gcd
gcd的和,然后还剩下一个
x
x
x,就看看
k
k
k能不能等于
x
i
+
任
意
多
个
g
c
d
x_i+任意多个gcd
xi+任意多个gcd,即判断
(
k
−
x
i
)
%
g
c
d
=
=
0
(k-x_i)\%gcd==0
(k−xi)%gcd==0。
#include "bits/stdc++.h" using namespace std; typedef long long ll; ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } void solve() { int _; cin >> _; while(_--) { int n; ll k; cin >> n >> k; vector<ll>v(n + 1); ll GCD; for(int i = 1;i <= n; i++) { cin >> v[i]; if(i == 2) { GCD = v[i] - v[i - 1]; } else { GCD = gcd(v[i] - v[i - 1], GCD); } } bool flag = false; for(int i = 1;i <= n; i++) { if((k - v[i]) % GCD == 0) { flag = true; break; } } cout << (flag ? "YES" : "NO") << endl; } } signed main() { solve(); }
题意:给两个01串,问经过q天之后能不能把s1转化成s2,每一天给一个区间,可以将该区间严格小于一半的字符数变成另一种,最后,如果可以转化输出YES,反之NO。
思路:
从第一天开始,后面的操作是基于前面的,所以我们需要时间逆序。
每一次操作,会有三种情况:
所以需要区间覆盖,想到区间问题,线段树是居家旅行的好东西。
直接用最简单的线段树模拟这个过程即可。
#include "bits/stdc++.h" using namespace std; const int N = 1e6 + 10; int n, q; string s1, s2; #define lc u << 1 #define rc u << 1 | 1 #define mid (t[u].l + t[u].r) / 2 struct Tree { int l, r; int sum; int tag; }t[N << 1]; inline void push_up(int u) { t[u].sum = t[lc].sum + t[rc].sum; } inline void push_down(int u) { if(t[u].tag == -1) return ; t[lc].sum = t[u].tag * (t[lc].r - t[lc].l + 1); t[rc].sum = t[u].tag * (t[rc].r - t[rc].l + 1); t[lc].tag = t[u].tag; t[rc].tag = t[u].tag; t[u].tag = -1; } void build(int u, int l, int r) { t[u].l = l; t[u].r = r; t[u].sum = 0; t[u].tag = -1; if(l == r) { t[u].sum = s2[l - 1] - '0'; return ; } int m = (l + r) >> 1; build(lc, l, m); build(rc, m + 1, r); push_up(u); } void modify(int u, int ql, int qr, int v) { if(ql <= t[u].l && t[u].r <= qr) { t[u].sum = v * (t[u].r - t[u].l + 1); t[u].tag = v; return ; } push_down(u); if(ql <= mid) modify(lc, ql, qr, v); if(qr > mid) modify(rc, ql, qr, v); push_up(u); } int query(int u, int ql, int qr) { if(ql <= t[u].l && t[u].r <= qr) { return t[u].sum; } push_down(u); int ans = 0; if(ql <= mid) ans += query(lc, ql, qr); if(qr > mid) ans += query(rc, ql, qr); return ans ; } void solve() { int _; cin >> _; while(_--) { cin >> n >> q; cin >> s1 >> s2; build(1, 1, n); vector<int> l(q + 1), r(q + 1); for(int i = 1;i <= q; i++) { cin >> l[i] >> r[i]; } bool flag = true; for(int i = q;i >= 1; i--) { int len = r[i] - l[i] + 1; int v = query(1, l[i], r[i]); if(v * 2 < len) modify(1, l[i], r[i], 0); else if(v * 2 > len) modify(1, l[i], r[i], 1); else { flag = false; break; } } for(int i = 1;i <= n; i++) { if(query(1, i, i) != s1[i - 1] - '0') { flag = false; break; } } cout << (flag ? "YES" : "NO") << endl; } } signed main() { solve(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。