Loading

F. Kirei and the Linear Function(字符串哈希 枚举)CF 1729F

F - Kirei and the Linear Function(前缀和,哈希,暴力)

题目:

​ 有一个长度为\(2e5\)的字符串和一个长度\(w\)。进行\(2e5\)次询问,每次给出\(l_i,r_i,k_i\),询问是否存在\(v(l, r)*v(L_1,L_1+w-1)+v(L_2,L_2+w-1) \bmod 9 == k_i\)

思路:

\(l,r\)是指定好的,无法更改,但是\(L_1,L_2\)是可以自由选择的。如果选择去枚举\(L\)的话,时间复杂度会非常大。我们可以对全部要查询的区间初始化后取模,进行前缀和+哈希处理。那么我们每次查询只需要枚举10^2就可以求解。

实现:

​ 题目提到,当有多个方案时,输出最小字典序的\(L\)的答案。在预处理的时候,我们只存储\(L\)位置最靠前的两个。最后我们用一个\(PII\)来更新我们的\(L_1, L_2\)

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
 
const int inf = 0x3f3f3f3f;
const int N = 200005;
int n;
char str[N];
int s[N];
int zero[N];
int w, m;
 
int calc(int l, int r) //用前缀哈希法 求v(l, r) % 9
{
    return ((s[r] - s[l - 1] * zero[r - l]) % 9 + 9) % 9;
}
 
void init() //为了求v(l, r)做的初始化
{
    zero[0] = 1;
    for(int i = 1; i <= n; i ++)
    {
        zero[i] = (zero[i - 1] * 10) % 9;
        s[i] = (s[i - 1] * 10 + str[i] - '0') % 9;
    }
}
 
void solve()
{
    scanf("%s", str + 1);
    n = strlen(str + 1);
    init();
    scanf("%d%d", &w, &m);  
    
    vector<int> v[11];
    for(int l = 1; l + w - 1 <= n; l ++) //预处理所有v(l, l + w - 1) % 9
    {
        int r = l + w - 1;
        int tmp = calc(l, r);
        if(v[tmp].size() < 2)
	        v[tmp].push_back(l);
    }
 
    while(m --)
    {
        PII res = {inf, inf};
        int l, r, k;
        scanf("%d%d%d", &l, &r, &k);
        int tmp = calc(l, r);
        for(int i = 0; i <= 9; i ++)
        {
            if(!v[i].size())    continue;
            for(int j = 0; j <= 9; j ++)
            {
                if(!v[j].size())    continue;
                if((tmp * i + j) % 9 == k)
                {
                    if(i == j && v[i].size() > 1)
                        res = min(res, {v[i][0], v[i][1]});
                    else if(i != j)  
                        res = min(res, {v[i][0], v[j][0]});
                }
            }
        }
        if(res.first == inf)    res = {-1, -1};
        printf("%d %d\n", res.first, res.second);
    }
}
 
signed main()
{
    int _;
    scanf("%d", &_);
    while(_--)
        solve();
}
posted @ 2022-09-16 16:38  DM11  阅读(80)  评论(0编辑  收藏  举报