Codeforces Round #361 (Div. 2) ABCDE题解

A. Mike and Cellphone

给出按手机键盘的顺序,判断号码是否唯一。

必须同时有按键出现在键盘的边缘,号码才会唯一。0也算边缘。

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 4e5 + 50;
const int MAXM = 2e5 + 50;

int n;
char s[10];

int main() {
#ifdef LOCAL_NORTH
    FIN;
#endif // LOCAL_NORTH
    while (~scanf("%d%s", &n, s)) {
        int ok1 = 0, ok2 = 0, ok3 = 0, ok4 = 0;
        for (int i = 0; s[i]; i++) {
            if (s[i] >= '1' && s[i] <= '3') {
                ok1 = 1;
            }
            if (s[i] == '7' || s[i] == '0' || s[i] == '9') {
                ok2 = 1;
            }
            if (s[i] == '1' || s[i] == '4' || s[i] == '7' || s[i] == '0') {
                ok3 = 1;
            }
            if (s[i] == '3' || s[i] == '6' || s[i] == '9' || s[i] == '0') {
                ok4 = 1;
            }
        }
        printf("%s\n", ok1 + ok2 + ok3 + ok4 == 4 ? "YES" : "NO");
    }
#ifdef LOCAL_NORTH
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
    return 0;
}

B. Mike and Shortcuts

一个从1到n的序列,从i可以到达i-1,i+1,以及a[i],每走一次消耗一点能量。输出从1出发到达每个点的最短消耗。

这题想也没想就dij了。。。其实O(n)的bfs更简单。。。

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;

int n, a[MAXN];
struct Edge {
    int to, w, nxt;
}E[MAXN << 2];
int Head[MAXN], tot;
void edge_init() {
    tot = 0;
    memset(Head, -1, sizeof(Head));
}
void edge_add(int u, int v, int w) {
    E[tot].to = v;
    E[tot].w = w;
    E[tot].nxt = Head[u];
    Head[u] = tot++;
}

struct Node {
    int v, val;
    Node(int vv, int vval) {
        v = vv;
        val = vval;
    }
    bool operator < (const Node& node) const {
        return val > node.val;
    }
};
int mincost[MAXN];
bool vis[MAXN];
void dijkstra(int start) {
    memset(mincost, INF, sizeof(mincost));
    memset(vis, false, sizeof(vis));
    priority_queue<Node> q;
    while (!q.empty())
        q.pop();
    mincost[start] = 0;
    q.push(Node(start, 0));
    while (!q.empty()) {
        Node cur = q.top();
        q.pop();
        int u = cur.v;
        if (vis[u])
            continue;
        vis[u] = true;
        for (int i = Head[u]; ~i; i = E[i].nxt) {
            int v = E[i].to;
            if (!vis[v] &&  mincost[v] > mincost[u] + E[i].w) {
                mincost[v] = mincost[u] + E[i].w;
                q.push(Node(v, mincost[v]));
            }
        }
    }
}

int main() {
#ifdef LOCAL_NORTH
    FIN;
#endif // LOCAL_NORTH
    while (~scanf("%d", &n)) {
        edge_init();
        for (int i = 1; i <= n; i++) {
            if (i != 1) {
                edge_add(i, i - 1, 1);
                edge_add(i - 1, i, 1);
            }
            int v;
            scanf("%d", &v);
            edge_add(i, v, 1);
        }
        dijkstra(1);
        for (int i = 1; i <= n; i++) {
            printf("%d%c", mincost[i], " \n"[i == n]);
        }
    }
#ifdef LOCAL_NORTH
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
    return 0;
}

C. Mike and Chocolate Thieves

给出一个n,输出一个最小的m。m要满足a*k^3<=m(a,k>0)的个数刚好等于n。

直接二分答案。对于mid,我们判断的方法:从1开始枚举k(k^3>n时break),对于每一个k,满足条件的a的个数就是mid/(k^3)。累加然后判断累加之和与n的关系即可。

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;

LL m;

LL work(LL n) {
    LL res = 0;
    for (LL i = 2; i <= INFLL; i++) {
        LL t = i * i * i;
        if (t > n)
            break;
        res += n / t;
    }
    return res;
}

int main() {
#ifdef LOCAL_NORTH
    FIN;
#endif // LOCAL_NORTH
    while (~scanf("%I64d", &m)) {
        LL l = 1, h = INFLL, ans = -1;
        while (l <= h) {
            LL mid = (l + h) / 2;
            LL t = work(mid);
            if (t >= m) {
                if (t == m) {
                    ans = mid;
                }
                h = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        printf("%I64d\n", ans);
    }
#ifdef LOCAL_NORTH
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
    return 0;
}

D. Friends and Subsequences

给出两个序列,输出a序列区间内最大值等于b序列区间内最小值的区间个数。

二分+RMQ。

首先可以知道,于是就有了单调性。

具体就是枚举左端点l,二分右端点r,求出满足=0的最小的rmin和最大的rmax(与lower_bound和upper_bound组合使用来计数的方法类似),然后ans+=rmax-rmin。区间最值可以用RMQ实现O(1)查询。

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define lowbit(x) ((x)&(-x))
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;

int n, a[MAXN], b[MAXN];

int dpa[MAXN][20], dpb[MAXN][20];
int mm[MAXN];
void initRMQ(int n) {
    mm[0] = -1;
    for(int i = 1; i <= n; i++) {
        mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
        dpa[i][0] = a[i];
        dpb[i][0] = b[i];
    }
    for(int j = 1; j <= mm[n]; j++)
        for(int i = 1; i + (1<<j) -1 <= n; i++) {
            dpa[i][j] = max(dpa[i][j-1],dpa[i+(1<<(j-1))][j-1]); //max可以改为任何积性函数
            dpb[i][j] = min(dpb[i][j-1],dpb[i+(1<<(j-1))][j-1]);
        }
}
int rmq(int x,int y) {
    int k = mm[y-x+1];
    return max(dpa[x][k],dpa[y-(1<<k)+1][k]) - min(dpb[x][k],dpb[y-(1<<k)+1][k]);
}

int main() {
#ifdef LOCAL_NORTH
    FIN;
#endif // LOCAL_NORTH
    while (~scanf("%d", &n)) {
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++)
            scanf("%d", &b[i]);
        initRMQ(n);
        LL ans = 0;
        for (int i = 1; i <= n; i++) {
            int l = i, h = n, a, b;
            while (l <= h) {
                int mid = (l + h) / 2;
                if (rmq(i, mid) >= 0) //lower_bound
                    h = mid - 1;
                else
                    l = mid + 1;
            }
            a = l - 1;
            l = i, h = n;
            while (l <= h) {
                int mid = (l + h) / 2;
                if (rmq(i, mid) > 0) //upper_bound
                    h = mid - 1;
                else
                    l = mid + 1;
            }
            b = l - 1;
            ans += (b - a);
        }
        printf("%I64d\n", ans);
    }
#ifdef LOCAL_NORTH
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
    return 0;
}

E. Mike and Geometry Problem

给出n个区间,求穷举k个区间相交,相交部分的整数个数。

离散化+组合数。

对于一个点i,如果有cnt个区间覆盖了它,那么它对最终答案的贡献就是。但是逐个枚举i是不可能的。

所以先把区间的左右端点离散化后排序。排序后的相邻两个数所组成的区间内的点,被覆盖的次数是相同的。所以用last来记录上一个端点,ans+=C(cnt,k)* (当前端点坐标-last)。O(n)枚举就好了。

还要注意一点,左端点记录的时候要减1,这样就能正确地计算[1,3]∩[3,5]这种情况了。

/*
                       ::
                      :;J7, :,                        ::;7:
                      ,ivYi, ,                       ;LLLFS:
                      :iv7Yi                       :7ri;j5PL
                     ,:ivYLvr                    ,ivrrirrY2X,
                     :;r@Wwz.7r:                :ivu@kexianli.
                    :iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur
                   ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17
                ;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i
              :,, ,,:   ,::ir@mingyi.irii:i:::j1jri7ZBOS7ivv,
                 ,::,    ::rv77iiiriii:iii:i::,rvLq@huhao.Li
             ,,      ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:
           :::  ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri
          ,     2OBBOi,iiir;r::        ,irriiii::,, ,iv7Luur:
        ,,     i78MBBi,:,:::,:,  :7FSL: ,iriii:::i::,,:rLqXv::
        :      iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::
       ,     ::::i   ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii
      ,       :       , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:
     ,               ,,,,::::i:  @arqiao.       ,:,, ,:::ii;i7:
    :,       rjujLYLi   ,,:::::,:::::::::,,   ,:i,:,,,,,::i:iii
    ::      BBBBBBBBB0,    ,,::: , ,:::::: ,      ,,,, ,,:::::::
    i,  ,  ,8BMMBBBBBBi     ,,:,,     ,,, , ,   , , , :,::ii::i::
    :      iZMOMOMBBM2::::::::::,,,,     ,,,,,,:,,,::::i:irr:i:::,
    i   ,,:;u0MBMOG1L:::i::::::  ,,,::,   ,,, ::::::i:i:iirii:i:i:
    :    ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::
    :     :rk@Yizero.i:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,
     :      5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i@petermu.,
          , :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::
              :jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:
           ,:  :@kevensun.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,
           ,,,     ,,:,::::::i:iiiii:i::::,, ::::iiiir@xingjief.r;7:i,
        , , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::
         :,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;@Secbone.ii:::
*****************************************************************************
                        Singing my song for my dream.
*****************************************************************************
*/

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define mp make_pair
#define pb push_back
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define lowbit(x) ((x)&(-x))
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
#define debug puts("-------------");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e9 + 7;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;

int n, k;
LL fac[MAXN];
vector<PII > seg;

LL fastpow(LL b, LL c) {
    LL res = 1;
    while (c) {
        if (c & 1)
            res = res * b % MOD;
        b = b * b % MOD;
        c >>= 1;
    }
    return res;
}

LL C(LL m, LL n) {
    if (n > m)
        return 0;
    LL up = fac[m], down = fac[n] * fac[m - n] % MOD;
    return up * fastpow(down, MOD - 2) % MOD;
}

int main() {
#ifdef LOCAL_NORTH
    FIN;
#endif // LOCAL_NORTH
    fac[0] = 1;
    for (int i = 1; i < MAXN; i++)
        fac[i] = fac[i - 1] * i % MOD;
    while (~scanf("%d%d", &n, &k)) {
        seg.clear();
        for (int i = 0; i < n; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            seg.pb(mp(a - 1, 1));
            seg.pb(mp(b, -1));
        }
        sort(seg.begin(), seg.end());
        LL ans = 0;
        int sz = seg.size(), last = seg[0].first, cnt = 0;
        for (int i = 0; i < sz; i++) {
            ans = (ans + C(cnt, k) * (seg[i].first - last)) % MOD;
            last = seg[i].first;
            cnt += seg[i].second;
        }
        printf("%I64d\n", ans);
    }
#ifdef LOCAL_NORTH
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值