2021.8.28 CCPC2021網絡賽


3題校內墊底的屑

1002:

循環節找到以后直接雙指針就行
考場上沒有細算循環節長度,按照1e5算的,交上去自然是wa。正解的循環節最大長度在\(2^3\times3^2\times5\times7\times11=27720\times n\),然后還可能有橫跨兩個循環節的部分,因此長度還要再乘個二。

// Problem: Time-division Multiplexing
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=1031
// Memory Limit: 262 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 107, maxm = 27720 * 100 * 2;
#define ll long long
int n, m, k, tot, T;
char s[maxm+7];
int rd() {
    int x;
    scanf("%d", &x);
    return x;
}
char a[107][14];
int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}
int lcm = 1, len[107], cnt[300], flag, ans, flag0;
int main() {
    T = rd();
    while (T--) {
        lcm = 1; ans = 999999999; tot = 0;
        memset(cnt, 0, sizeof(cnt));
        flag = 0;
        n = rd();
        for (int i = 1; i <= n; i++) {
            scanf("%s", a[i]);
            k = strlen(a[i]);
            for (int j = 0; j < k; j++) {
                if (cnt[a[i][j]]==0) {
                    flag++;
                }
                cnt[a[i][j]]++;
            }
            len[i] = k;
            lcm = k * lcm / gcd(k, lcm);    
        }
        lcm = lcm*2*n;
        for (int cur = 0; tot < lcm; cur++) {
            for (int i = 1; i <= n; i++) {
                s[tot++] = a[i][cur%len[i]];
            }
        }
        int l = 0, r = -1;
        flag0 = flag;
        flag = 0;
        memset(cnt, 0, sizeof(cnt));
        while (r < lcm) {
            while (flag < flag0 && r < lcm) {
                r++;
                if (r == lcm) break;
                if (cnt[s[r]] == 0) {
                    flag++;
                }
                cnt[s[r]]++;
            }
            if (r == lcm) break;
            while (flag == flag0 && l < r) {
                cnt[s[l]]--;
                if (cnt[s[l]] == 0) {
                    flag--;
                } 
                l++;
                if (flag == flag0)
                    ans = min(ans, r-l+1);
            }
            if (flag == flag0 && l <= r) 
            	ans = min(ans, r-l+1);    
        }
        
        //printf("s == %s\n", s);
        printf("%d\n", ans);
    }
    return 0;
}

1011:

這里放洛谷1174的題解吧
https://www.cnblogs.com/YjmStr/p/15208056.html

1012:

wa傻了,待補。
upd:如果f[i]等於0,那么f[i]不能用來向后轉移,對拍和正解同時犯了這個錯誤


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM