• CF_EDU51 E. Vasya and Big Integers


    传送门:https://codeforces.com/contest/1051/problem/E

    题意:

      把一个数分成许多小段,每一段的值在L和R间。问有多少种分法。

    思路 :

      首先,需要快速处理出每个位子 ,最近和最远可以组合的区间。如何处理这个区间,由于时限比较紧张,可以用哈希的方法,因为是长度固定,所以可以用二分确定两端长度前缀,再比较大小的方法。当然哈希要用比较好的双哈希。

      然后,我们可以从后往前dp,每个位子的答案 = 这个位子对应区间的值的和。

    #include <algorithm>
    #include  <iterator>
    #include  <iostream>
    #include   <cstring>
    #include   <cstdlib>
    #include   <iomanip>
    #include    <bitset>
    #include    <cctype>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <stack>
    #include     <cmath>
    #include     <queue>
    #include      <list>
    #include       <map>
    #include       <set>
    #include   <cassert>
    
    using namespace std;
    #define lson (l , mid , rt << 1)
    #define rson (mid + 1 , r , rt << 1 | 1)
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define pb push_back
    #define pq priority_queue
    
    
    
    typedef long long ll;
    typedef unsigned long long ull;
    //typedef __int128 bll;
    typedef pair<ll ,ll > pll;
    typedef pair<int ,int > pii;
    typedef pair<int,pii> p3;
    
    //priority_queue<int> q;//这是一个大根堆q
    //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
    #define fi first
    #define se second
    //#define endl '
    '
    
    #define OKC ios::sync_with_stdio(false);cin.tie(0)
    #define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
    #define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
    #define max3(a,b,c) max(max(a,b), c);
    #define min3(a,b,c) min(min(a,b), c);
    //priority_queue<int ,vector<int>, greater<int> >que;
    
    const ll mos = 0x7FFFFFFF;  //2147483647
    const ll nmos = 0x80000000;  //-2147483648
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f; //18
    const int mod = 998244353;
    const double esp = 1e-8;
    const double PI=acos(-1.0);
    const double PHI=0.61803399;    //黄金分割点
    const double tPHI=0.38196601;
    
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    /*-----------------------showtime----------------------*/
                const int maxn = 1e6+9;
                const int base = 37;
                const int base2 = 71;
                const int MOD = 1e9+7;
                //const ll MOD2 = 1e16+17;
                int dple[maxn],dpri[maxn];
                int lenle,lenri;
                ll dp[maxn],sum[maxn];
                struct hash
                {
                    char s[maxn];
                    ll h1[maxn],qp1[maxn];
                    ull h2[maxn],qp2[maxn];
                    ll p1[maxn],p2[maxn],len,val1[maxn],val2[maxn];
    
                    void init()
                    {
                        h1[0]=val1[0]=0;
                        qp1[0]=p1[0]=1;
                        len=strlen(s+1);
                        for(int i=1;i<=len;i++)
                        {
                            qp1[i]=(qp1[i-1]*base)%MOD;
                            h1[i]=(h1[i-1]*base%MOD+s[i])%MOD;
                        }
    
                        h2[0]=val2[0]=0;
                        qp2[0]=p2[0]=1;
                        for(int i=1;i<=len;i++)
                        {
                            qp2[i]=(qp2[i-1]*base2);
                            h2[i]=(h2[i-1]*base2+s[i]);
                        }
                    }
                    ll get_hash1(int l,int r)
                    {
                        return ((h1[r]-h1[l-1]*qp1[r-l+1])%MOD +MOD )% MOD;
                    }
                    ull get_hash2(int l,int r)
                    {
                        return ((h2[r]-h2[l-1]*qp2[r-l+1]));
                    }
                }A,L,R;
    
                bool checkle(int l1, int r1) {
                        int le = l1, ri = r1;
                        while(le <= ri){
                            int mid = (le + ri) >> 1;
                            if(A.get_hash1(le,mid) == L.get_hash1(le-l1+1,mid-l1+1)  && A.get_hash2(le,mid) == L.get_hash2(le-l1+1,mid-l1+1)){
                                le = mid+1;
                            }
                            else ri = mid - 1;
                        }
                        if(le == r1 + 1) return true;
                        return A.s[le] >= L.s[le - l1 + 1];
                }
    
                bool checkri(int l1,int r1) {
                        int le = l1, ri = r1;
    
                        while(le <= ri){
                            int mid = (le + ri) >> 1;
    
                            if(A.get_hash1(le,mid) == R.get_hash1(le-l1+1,mid-l1+1) &&A.get_hash2(le,mid) == R.get_hash2(le-l1+1,mid-l1+1) ){
                                le = mid+1;
                            }
                            else ri = mid-1;
                        }
                        if(le == r1 + 1) return true;
                        return A.s[le] <= R.s[le - l1 + 1];
                }
    
    
    int main(){
                scanf("%s%s%s", A.s + 1, L.s + 1,R.s + 1);
                A.init();   L.init();   R.init();
    
                ll len = A.len;
                int n = len;
                lenle = L.len; lenri = R.len;
                for(int i=1; i<=n; i++){
                    int le = i, ri = n;
                    dple[i] = -1; dpri[i] = -1;
                    if(A.s[i] == '0') {
                            if(L.s[1] == '0') dple[i] = i,dpri[i] = i;
                            else dple[i] = -1,dpri[i] = -1;
                            continue;
                    }
    
                    if(i + lenle - 1<= n &&  checkle(i, i + lenle - 1)) dple[i] = i + lenle - 1;
                    else if(i + lenle<=n)dple[i] = i + lenle;
    
    
                    if(i + lenri - 1<= n&& checkri(i, i + lenri -1)) dpri[i] = i + lenri - 1;
                    else dpri[i] = min(n,i+lenri-2);
    
                }
    
                sum[n+1] = 1;
                for(int  i=n; i>=1; i--){
                    int pl = dple[i] + 1,pr = dpri[i] + 1;
    
                    dp[i] = ((sum[pl] - sum[pr + 1] ) % mod + mod )%mod;
                    sum[i] = (sum[i+1] + dp[i]) % mod;
                }
    
                cout<<dp[1]<<endl;
                return 0;
    }
    View Code
  • 相关阅读:
    数组的基本操作
    面向对象
    继承
    JavaBean规范
    JVM内存模型
    数组的排序
    this
    访问控制权限
    数组
    方法的重载
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/10334503.html
Copyright © 2020-2023  润新知