Educational Codeforces Round 17

传送门:http://codeforces.com/contest/762

A题:求出n的第k个因子,不存在则输出-1,直接sqrt暴力找一下就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
vector <ll> V;
int main()
{
    V.pb(0);
    ll n, k;
    cin >> n >> k;
    ll m = sqrt((double)n);
    for (ll i = 1; i < m; i++)
    {
        if (n % i == 0)
        {
            V.pb(i);
            V.pb(n / i);
        }
    }
    if (n % m == 0) {
        if (m*m == n) V.pb(m);
        else V.pb(m), V.pb(n / m);

    }
    sort(V.begin(), V.end());
    if (k >= V.size()) cout << -1 << endl;
    else cout << V[k] << endl;
    return 0;
}
View Code

B题:有三种电脑,需要usb型的鼠标有a个,需要 PS/2型的鼠标有b个,两种鼠标都适配的电脑有c个,然后给你m种鼠标,每个鼠标价钱为vali,后面跟着型号,问适配所有电脑的最小花费。直接贪心就好了,先对价格进行排序,然后尽可能先把只能适配一种型号的匹配掉,再考虑两种通用的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, string> pis;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
pis N[3*maxn];
int main()
{
    int a, b, c, m;
    cin >> a >> b >> c;
    cin >> m;
    ll ans = 0;
    ll tol = a + b + c;
    for (int i = 0; i < m; i++)
    {
        cin >> N[i].X >> N[i].Y;
    }
    sort(N, N + m);
    for (int i = 0; i < m; i++)
    {
        if (N[i].Y == "USB")
        {
            if (a)
            {
                a--;
                ans += N[i].X;
            }
            else if (c)
            {
                c--;
                ans += N[i].X;
            }
        }
        else
        {
            if (b)
            {
                b--;
                ans += N[i].X;
            }
            else if (c)
            {
                c--;
                ans += N[i].X;
            }
        }
    }
    tol -= a + b + c;
    cout << tol << " " << ans << endl;
    return 0;
}
View Code

C题:给你两个字符串str1和str2,问在str2中删除一段的字符串(连续的字符)后,str2能变成str1的子序列,求删除的这段字符串的长度最小时,str2的剩余字符串是什么。这题题解是哈希和尺取,不过我不知道怎么做,我的做法是直接处理出pre[]和suf[],pre[i]代表str2中前i个字符在str1中匹配的位置,比如pre[i]=k,那str2[1]到str2[i]这段字符串就是str1[1]到str1[k]这段字符串的子序列(字符串下标从1开始)。而suf数组和pre数组差不多,不过处理的是后缀。

举个例子,对于

abccba

ba

pre:2 6

suf:5 6

这样处理出来后,我们只要找到pre和suf的两个数pre[i]和suf[j],如果pre[i]<suf[j],那么我们取str2[1]到str2[pre[i]]加上str2[suf[j]]到str2字符串结尾这段字符串一定是str1的子序列,且这字符串也是str2删掉一段字符串后得来的。那么我们只需要枚举pre[i],然后二分找出suf[j]>pre[i]的数字,然后更新一下最值就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define in() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int pre[maxn], suf[maxn], lens1, lens2;
char s1[maxn], s2[maxn];

void debug()
{
    for (int i = 0; i <= lens2; i++)
        printf("%d ", pre[i]);
    puts("");
    for (int i = 0; i <= lens2; i++)
        printf("%d ", suf[i]);
    puts("");
}

void init()
{
    lens1 = strlen(s1 + 1), lens2 = strlen(s2 + 1);
    int pos = 1;
    for (int i = 1; i <= lens2; i++)
    {
        pre[i] = INF;
        for (; pos <= lens1; pos++)
        {
            if (s2[i] == s1[pos])
            {
                pre[i] = pos;
                pos++;
                break;
            }
        }
    }
    pos = lens1;
    for (int i = lens2; i > 0; i--)
    {
        suf[i] = -1;
        for (; pos > 0; pos--)
        {
            if (s2[i] == s1[pos])
            {
                suf[i] = pos;
                pos--;
                break;
            }
        }
    }
    debug();
}

void solve()
{
    int ans = INF, l = 1, r = lens2;
    for (int i = 0; i <= lens2; i++)
    {
        int pos = upper_bound(suf + 1, suf + lens2 + 1, pre[i]) - suf;
        if (pre[i] == INF || suf[pos] == -1) continue;
        if (i >= pos) pos = i + 1;
        int Len = pos - i + 1;
        if (Len < ans)
        {
            ans = Len;
            l = i;
            r = pos;
        }
    }
    for (int i = 1; i <= l; i++)
        putchar(s2[i]);
    for (int i = r; i <= lens2; i++)
        putchar(s2[i]);
    puts(r - l <= lens2 ? "" : "-");
}

int main()
{
    scanf("%s%s", s1 + 1, s2 + 1);
    init();
    solve();
    return 0;
}
View Code

2017-01-30 17:33:41 

posted @ 2017-01-30 17:34  酱油党gsh  阅读(184)  评论(0编辑  收藏  举报