JZOJ5856. 【NOIP提高组模拟A组2018.9.8】 01 串

Description

某日,小 Q 得到了一种新的生成 01 串的代码
给定一个整数 Z,执行 n 次下列语句会得到一个 01 串
z=[(a*z+c)/k]%m;
if (z

Input

第一行五个整数 a, c, k, m, n。
第二行 n 个连续的 01 数字描述 01 串。

Output

一行一个整数表示答案

Sample Input

3 6 2 9 2
10

Sample Output

4

Data Constraint

对于 30%的数据,1<=n,m<=10^3
对于 60%的数据,1<=n<=10^3
对于 100%的数据,1<=n<=10^5,1<=m<=10^6,0<=a,c<=m,1<=k<=m,0<=z< m

题解

考虑字符串哈希。
fi,j f i , j 表示i为z的初始值,进行 2j 2 j 次变化之后,得到的字符串的哈希值。
gi,j g i , j 表示i为z的初始值,进行了 2j 2 j 次变化后,得到的数。
这两个都是可以通过倍增得到,字符串的哈希值可以将两个字符串拼接得到,
最后,枚举z,倍增判断是否合法。

code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return aabs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

const ll mo=10890604,w=31;
int a,c,k,m,mm,n,p[N],ans,_2[23],g[17][N*10];
ll f[17][N*10],s,t,z[N];

bool check(int x)
{
    t=0;
    for(int i=16;i+1;i--)
        if(n&_2[i])t=(t*z[_2[i]]%mo+f[i][x])%mo,x=g[i][x];
    return t==s;
}

int main()
{
    freopen("zero.in","r",stdin);
    freopen("zero.out","w",stdout);

    _2[0]=z[0]=1;
    for(int i=1;i<20;i++)_2[i]=_2[i-1]<<1;
    scanf("%d%d%d%d%d",&a,&c,&k,&m,&n);
    for(ch=G();ch!='1' && ch!='0';ch=G());
    for(int i=1;i<=n;i++)
        p[i]=ch-48,ch=G(),z[i]=z[i-1]*w%mo,s=s*w%mo+p[i];
    mm=m>>1;

    for(int i=0;i<m;i++)g[0][i]=(((ll)i*a+c)/k)%m,f[0][i]=(g[0][i]>=mm);

    for(int j=1;j<17;j++)
        for(int i=0;i<m;i++)
            g[j][i]=g[j-1][g[j-1][i]],
            f[j][i]=(f[j-1][g[j-1][i]]+f[j-1][i]*z[_2[j-1]]%mo)%mo;

    for(int i=0;i<m;i++)
        if(check(i))ans++;

    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(题解,hash)