CF665

CF665

CF665A

link

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 1jm ),令 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

link

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

link

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

link

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 1i<jn
  • a i ⊕ a i + 1 ⊕ . . . ⊕ a j ⩾ k a_i\oplus a_{i+1}\oplus ...\oplus a_j\geqslant k aiai+1...ajk

CF665E题解

首先设 c i = a 1 ⊕ a 2 ⊕ . . . ⊕ a i c_i=a_1\oplus a_2 \oplus...\oplus a_i ci=a1a2...ai
问题转化为

  • 1 ≤ i < j ≤ n 1\le i < j\le n 1i<jn
  • c i − 1 ⊕ c j ⩾ k c_{i-1}\oplus c_j\geqslant k ci1cjk

然后发现这玩意可以 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

link

CF665F题意

给一个整数 n ( n ≤ 1 0 11 ) n(n\le 10^{11}) n(n1011),问 [ 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=1primein (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 meissellehmer 就可以完美过了这道题啦(虽然我不会)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值