CF665
CF665A
CF665A题意
A A A市和 B B B市之间有公交车行驶,第一班是早上 5 : 00 5:00 5:00,最后一班不迟于晚上 11 : 59 11:59 11:59开出。
从 A A A市出发的公共汽车每隔 a a a分钟发车,到 B B B市需 t a t_a ta分钟,从 B B B市出发的公共汽车每隔 b b b分钟发一辆车,到 A A A市需 t b t_b tb分钟。
司机
S
i
m
o
n
Simon
Simon吃饱了没事干增加工作的乐趣,数了数在他的行程途中向他驶来的公交车,但
S
i
m
o
n
Simon
Simon没有计算他在起点和终点遇到的公共汽车。
给定
S
i
m
o
n
Simon
Simon从
A
A
A城到
B
B
B城的时间,计算Simon将会见到的公共汽车的数量。
CF665A题解
Eric特有的被红题爆杀
直接模拟下
B
B
B 车出发的时间会不会被看到就好了
CF665A代码
#include<bits/stdc++.h>
using namespace std;
int a, ta, b, tb, x, y;
signed main(){
scanf("%d%d",&a,&ta);
scanf("%d%d",&b,&tb);
scanf("%d:%d",&x,&y);
int tmp = (x - 5) * 60 + y;
int i = 0,cnt = 0;
while(i < tmp + ta && i <= 18 * 60 + 59){
if(i + tb > tmp)cnt++;i += b;
}
printf("%d\n",cnt);
return 0;
}
CF665B
CF665B题意
小
W
W
W 的商店开始了线上购物,线下提货的服务。商店有
k
k
k 个商品(编号
1
1
1 到
k
k
k),
n
n
n 个用户使用了这项服务。
每个用户的订单都包含
m
m
m 个商品,并在线付费,以
a
i
,
j
a_{i,j}
ai,j 表示第
i
i
i 个用户的订单中第
j
j
j 个商品的编号。
所有的商品是排成一排的,在小
W
W
W 收到第
i
i
i 件商品时,他会从前向后找所有的商品
a
i
j
a_{ij}
aij (
1
≤
j
≤
m
1\le j\le m
1≤j≤m ),令
p
o
s
(
x
)
pos(x)
pos(x) 表示该用户需要的编号为
x
x
x 的商品,此时在序列中的位置。
小
W
W
W 需要
p
o
s
(
a
i
1
)
+
p
o
s
(
a
i
2
)
+
.
.
.
+
p
o
s
(
a
i
m
)
pos(a_{i1})+pos(a_{i2})+...+pos(a_{im})
pos(ai1)+pos(ai2)+...+pos(aim) 为第
i
i
i 个客户服务的时间。
当小
W
W
W 访问第
x
x
x 个元素时,他会将新的存货放到最前面,并将位置为
x
x
x 的元素移除,因此,此序列是在不断更新的。你需要算出小
W
W
W 需要的时间。假设市场上有无尽的存货。
CF665B题解
为啥这套题题面都这么长
直接模拟就好了反正
O
(
n
3
)
O(n^3)
O(n3) 也能过
CF665B代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
return x * f;
}
const int maxn = 200;
int n, m, k;
vector<int> vec;
signed main(){
n = read(); m = read(); k = read();
for(int i = 1;i <= k;i++){vec.push_back(read());}
int ans = 0;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
int x = read(), t = 0;
for(t = 0;t < vec.size();t++){if(vec[t] == x)break;}
vec.erase(vec.begin() + t);
vec.insert(vec.begin(),x);
ans += t + 1;
}
}
printf("%d\n",ans);
return 0;
}
CF665C
CF665C题意
给一个字符串,让你尽可能少的改其中的字符,使得字符串相邻的字符不相同,给出任意方案都可以
CF665C题解
想到每次改一段连续相同字符的时候只需要满足奇不变偶变就好了:)
CF665C代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n;char A[maxn], B[maxn];
signed main(){
scanf("%s",A + 1);n = strlen(A + 1);
for(int i = 1;i <= n;i++){
int j = i;while(A[j + 1] == A[i])j++;
char ch = 'a';while(A[j + 1] == ch || A[i] == ch)ch++;
bool book = 0;
for(int k = i;k <= j;k++){B[k] = book ? ch : A[i];book = !book;}
i = j;
}
for(int i = 1;i <= n;i++)putchar(B[i]);
puts("");
return 0;
}
CF665D
CF665D题意
给一个序列 a 1 , 2 , . . . , n a_{1,2,...,n} a1,2,...,n,要求找出其子序列满足任意两个数加和是质数
CF665D题解
很容易发现最后的子序列是以下三种之一
- 全是 1 1 1,如果有一个数是质数减一就在带一个
- 一个奇数加一个偶数是质数
- 随便挑一个数
然后做就完了~~~~~~吗?
亿堆细节慢慢写吧
CF665D代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
return x * f;
}
const int maxn = 1e3 + 10;
int a[maxn], n;
bool book[maxn * maxn * 4];
int prime[maxn * maxn], tot;
vector<int> ans1,ans2,ans3;
signed main(){
for(int i = 2;i <= 3e6;i++){
if(!book[i])prime[++tot] = i;
for(int j = 1;j <= tot && i * prime[j] <= 3e6;j++){
book[i * prime[j]] = 1;
if(i % prime[j] == 0)break;
}
}
n = read();
for(int i = 1;i <= n;i++){a[i] = read();if(a[i] == 1)ans1.push_back(1);}
bool book2 = false, book1 = false;
ans3.push_back(a[1]);
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n && !book2;j++)
if(!book[a[i] + a[j]] && !book2 && i != j){
ans2.push_back(a[i]);ans2.push_back(a[j]);
book2 = true;break;
}
if(ans1.size() && !book[a[i] + 1] && !book1 && a[i] != 1){
book1 = true;ans1.push_back(a[i]);
}
}
if(ans2.size() >= ans1.size() && ans2.size() >= ans3.size()){
printf("%d\n",ans2.size());for(int i : ans2)printf("%d ",i);
}
else if(ans1.size() >= ans2.size() && ans1.size() >= ans3.size() && ans1[0] == 1){
printf("%d\n",ans1.size());for(int i : ans1)printf("%d ",i);
}
else{
printf("%d\n",ans3.size());for(int i : ans3)printf("%d ",i);
}
return 0;
}
CF665E
CF665E题意
给一个序列 a 1 , 2 , . . . , n a_{1,2,...,n} a1,2,...,n 求出有多少个点对 ( i , j ) (i,j) (i,j) 满足
- 1 ≤ i < j ≤ n 1\le i < j\le n 1≤i<j≤n
- a i ⊕ a i + 1 ⊕ . . . ⊕ a j ⩾ k a_i\oplus a_{i+1}\oplus ...\oplus a_j\geqslant k ai⊕ai+1⊕...⊕aj⩾k
CF665E题解
首先设
c
i
=
a
1
⊕
a
2
⊕
.
.
.
⊕
a
i
c_i=a_1\oplus a_2 \oplus...\oplus a_i
ci=a1⊕a2⊕...⊕ai
问题转化为
- 1 ≤ i < j ≤ n 1\le i < j\le n 1≤i<j≤n
- c i − 1 ⊕ c j ⩾ k c_{i-1}\oplus c_j\geqslant k ci−1⊕cj⩾k
然后发现这玩意可以
t
r
i
e
trie
trie
然后有笨蛋写
t
r
i
e
trie
trie 的时候
bool v = u >> i;
就没有
(
u
>
>
i
)
&
1
(u >> i) \& 1
(u>>i)&1
是谁呢?
我不说啊啊啊啊啊ばか
CF665E代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int x = 0, f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
return x * f;
}
const int maxn = 1e6 + 10;
int n, a[maxn], c[maxn], K;
int trie[maxn * 30][2], tot = 1;
ll cnt[maxn * 30];
void insert(int x){
int u = 1;
// printf("x=%d\n",x);
for(int i = 31;i + 1;i--){
bool v = (x >> i) & 1;
if(!trie[u][v])trie[u][v] = ++tot;
u = trie[u][v];cnt[u]++;
// printf("u=%d->",u);
}
// printf("u=%d\n",u);
}
ll query(int x,int k){
int u = 1;ll ans = 0;
for(int i = 31;i + 1;i--){
bool v = (x >> i) & 1, ki = (k >> i) & 1;
if(!ki){ans += cnt[trie[u][!v]];u = trie[u][v];}
else{u = trie[u][!v];}
}
return ans;
}
signed main(){
// freopen("CF665E.out","w",stdout);
n = read(); K = read();
for(int i = 1;i <= n;i++){a[i] = read(); c[i] = c[i - 1] ^ a[i];}
ll ans = 0;
// for(int i = 1;i <= 40;i++)printf("cnt[%d]=%lld\n",i,cnt[i]);
for(int i = 0;i <= n;i++){
ll tmp = query(c[i],K - 1);
// printf("%lld\n",tmp);
ans += tmp; insert(c[i]);
}
printf("%lld\n",ans);
return 0;
}
CF665F
CF665F题意
给一个整数 n ( n ≤ 1 0 11 ) n(n\le 10^{11}) n(n≤1011),问 [ 1 , n ] [1,n] [1,n] 之间约数只有 4 4 4 个的数字有多少个
CF665F题解
不难推出,如果满足性质,需要满足以下两点之一
- 由两个不相同质数相乘而来
- 是一个质数的三次方
然后发现
n
≤
1
0
6
\sqrt{n} \le 10^6
n≤106 可以暴力枚举
于是乎答案变成了
a
n
s
=
f
(
3
n
)
+
∑
i
=
1
p
r
i
m
e
i
≤
n
(
f
(
n
p
r
i
m
e
i
)
−
f
(
p
r
i
m
e
i
)
)
ans=f(^3\sqrt{n})+\sum_{i=1}^{prime_i\le \sqrt{n}}(f(\frac{n}{prime_i})-f(prime_i))
ans=f(3n)+∑i=1primei≤n(f(primein)−f(primei)),其中
f
(
i
)
f(i)
f(i) 表示小于等于
i
i
i 的质数的数量
一刻也没有为不会meissel-lehmer感到悲哀,立刻赶到的是…题解!
然后用
m
e
i
s
s
e
l
−
l
e
h
m
e
r
meissel-lehmer
meissel−lehmer 就可以完美过了这道题啦(虽然我不会)
CF665F代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 10;
int n;
bool book[maxn];
const int N = 1e6 + 10;
const int M = 7; //为了减小内存可以不过是质数
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17; //为了减小内存可以不过要按质数减小如去掉17
bool np[N];
int pr[maxn], tot;
int prime[N], pi[N];
int phi[PM + 1][M + 1], sz[M + 1];
int cnt = 0;
int getprime() {
np[0] = np[1] = true;
pi[0] = pi[1] = 0;
for (int i = 2; i < N; ++i) {
if (!np[i]) prime[++cnt] = i;
pi[i] = cnt;
for (int j = 1; j <= cnt && i * prime[j] < N; ++j) {
np[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
return cnt;
}
void init() {
getprime();
sz[0] = 1;
for (int i = 0; i <= PM; ++i) phi[i][0] = i;
for (int i = 1; i <= M; ++i) {
sz[i] = prime[i] * sz[i - 1];
for (int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
}
}
int sqrt2(int x) {
int r = (int)sqrt(x - 0.1);
while (r * r <= x) ++r;
return (int)(r - 1);
}
int sqrt3(int x) {
int r = (int)cbrt(x - 0.1);
while (r * r * r <= x) ++r;
return (int)(r - 1);
}
int getphi(int x, int s) {
if (s == 0) return x;
if (s <= M) return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
if (x <= prime[s] * prime[s]) return pi[x] - s + 1;
if (x <= prime[s] * prime[s] * prime[s] && x < N) {
int s2x = pi[sqrt2(x)];
int ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
for (int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];
return ans;
}
return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
}
int getpi(int x) {
if (x < N) return pi[x];
int ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
for (int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;
return ans;
}
int lehmer_pi(int x) { //小于等于n的素数有多少个
if (x < N) return pi[x];
int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
int b = (int)lehmer_pi(sqrt2(x));
int c = (int)lehmer_pi(sqrt3(x));
int sum = getphi(x, a) + (int)(b + a - 2) * (b - a + 1) / 2;
for (int i = a + 1; i <= b; i++) {
int w = x / prime[i];
sum -= lehmer_pi(w);
if (i > c) continue;
int lim = lehmer_pi(sqrt2(w));
for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);
}
return sum;
}
signed main(){
scanf("%lld",&n);int len = sqrt(n);init();
int sum = lehmer_pi(cbrt(n));
for(int i = 1;i <= cnt && prime[i] < len;i++){
// printf("pr[%lld]=%lld sum=%lld\n",i,prime[i],sum);
sum += lehmer_pi(n / prime[i]) - lehmer_pi(prime[i]);
}
printf("%lld\n",sum);
return 0;
}