HDU7055 - Yiwen with Sqc


https://acm.hdu.edu.cn/showproblem.php?pid=7055

思路1

考慮dp結果,dp[i]表示以i為結尾的答案
每次新進入一個字符,計算其對答案產生的貢獻

char s[maxn];
int t, cnt[30], sum[30];
ll dp[maxn];

void solve() {
    cin >> t;
    while (t--) {
        memset(cnt, 0, sizeof(cnt));
        memset(sum, 0, sizeof(sum));
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        ll ans = 0;
        for (int i = 1; i <= n; i++) {
            int now = s[i] - 'a' + 1;
            dp[i] = (dp[i - 1] + 2 * sum[now] + i) % mod;
            sum[now] = (sum[now] + i) % mod;
            ans = (ans + dp[i]) % mod;
        }
        printf("%lld\n", ans);
    }
}

思路2

對每個字符分開考慮.
假設現在有a,b,c,d位置上有1,那么這個區間的貢獻就是(1+1+1+1)^2,拆開來看
a^2 + b^2 + c^2 + d^2 + 2ab+2ac+2ad...
考慮c在這個區間產生的貢獻: c^2 + 2ac + 2bc + 2cd,
那么對於[a-1,d],[a-2,d]...[a-x,d+y]求個sum就能得到c產生的答案,挨個計算每個1產生的貢獻即可
其中用到了前綴和維護下就行

const int maxn = 1e5 + 7;
const int mod = 998244353;

int n, t, m;
char s[maxn];
int dp[maxn];

void solve() {
    cin >> t;
    while (t--) {
        cin >> (s + 1);
        n = strlen(s + 1);
        ll res = 0;
        for (char c = 'a'; c <= 'z'; c++) {
            memset(dp, 0, sizeof(dp));
            int cnt = 0, p = 0;
            for (int i = 1; i <= n; i++) {
                if (s[i] == c) {
                    res += i * (n - i + 1);
                    res %= mod;
                    ++p, dp[p] = dp[p - 1] + i;
                    res += 2ll * (n - i + 1) * dp[p - 1];
                    res %= mod;
                }
            }
        }
        cout << res << endl;
    }
}


免責聲明!

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



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