对于某唤做赛区难度的题,我只能是内流满面。。拿到题,A神题不可做,B,神题不可做,C,神题不可做。。。最后yy了一个A的算法。。。只得了20 TAT。C题骗分似乎有50 。。B题本来想骗分。。然后/ 写成 % 了。。 听说/ 可得80 。。

算了写题解吧。。 A暂时不会。。早上听了再写

B:

这个题得写法太过于机智了。。三种a, b, ans, 将ans 和 a 作为i, j。。何不奇葩。。首先需要明白对于a选b中的元素,选后面的不如取前面的,每转移一次看是否能对答案进行更新,然后在看是否能够转移,应为ai与bi的相等的位置是呈单调递增的,所以对与一个ai,找到一个比当前已经匹配了的点后最近的一个与ai想对应的进行转移。但是二分的时候要特判一下会不会这个对应为空或一定不合法。。。。我re 90了30分钟就是这个地方。。还有while的判断不要再写抽了。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int maxn = 102000;
const int maxv = 310;
const int inf = 0x3f3f3f3f;

int n, m, s, e;

int a[maxn], b[maxn];

vector <int> pos[maxn];

int f[maxn][maxv];
int smax = 0;

void read() {
    scanf("%d%d%d%d", &n, &m, &s, &e);
    for(int i = 1; i <= n; ++ i) {
        scanf("%d", &a[i]);
    }
    smax = s / e + 1;
    for(int i = 1; i <= m; ++ i) {
        scanf("%d", &b[i]);
        pos[b[i]].push_back(i);
    }
    a[0] = b[0] = -1;
}

int ans = 0;

void sov() {
    memset(f, inf, sizeof(f));
    f[0][0] = 0;
    for(int i = 1; i <= n; ++ i) {
        f[i][0] = 0;
        for(int j = 1; j <= smax; ++ j) {
            f[i][j] = f[i - 1][j];
            int ls = -1; int rs = pos[a[i]].size() - 1;
            if(rs < 0 || pos[a[i]][rs] <= f[i - 1][j - 1]) continue;
            while(rs - ls > 1) { 
                int mid = (ls + rs) >> 1;
                if(pos[a[i]][mid] > f[i - 1][j - 1]) rs = mid;
                else ls = mid;
                }
            if(rs < pos[a[i]].size()) f[i][j] = min(f[i][j], pos[a[i]][rs]);
            if(e * j + i + f[i][j] <= s) ans = max(ans, j); 
        }
    }
    printf("%d\n", ans);
}

int main() {
    read(); 
    sov();
    return 0;
}

 

C: 现在想想好水。。按照背包的思路(类似。。反正hobo大神说类似。。)搞搞就有了。。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 1100;
const int maxv = 10100;
int a[maxn]; int n;
int f[maxv];

int smax = 0;

void read() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) {
        scanf("%d", &a[i]);
        smax = max(smax, a[i]);
    }
}

int gcd(int a, int b) {
    return a % b == 0 ? b : gcd(b, a % b);
}

void sov() {
    memset(f, -1, sizeof(f));
    for(int i = 1; i <= n; ++ i) {
        for(int j = 1; j <= smax; ++ j) {
            if(f[j] != -1 || j == a[i]) { 
                if(f[j] == -1) f[j] = 1;
                else {
                    if(f[gcd(j, a[i])] == -1) f[gcd(j, a[i])] = f[j] + 1;
                    else f[gcd(j, a[i])] = min(f[gcd(j, a[i])], f[j] + 1);
                }
            }
        }
    }
    int G = a[1];
    for(int i = 2; i <= n; ++ i) {
        G = gcd(a[i], G);
    }
    printf("%d\n",n - f[G]);
}

int main() {
    read();  sov();
    return 0;
}