• 数论(同余+hash)


    Time Limit:3000MS Memory Limit:65536KB

    Description You are given a sequence a[0]a[1] ... a[N-1] of digits and a prime number Q. For each i<=j with a[i] != 0, the subsequence a[i]a[i+1]...a[j] can be read as a decimal representation of a positive integer. Subsequences with leading zeros are not considered. Your task is to count the number of pairs (i, j) such that the corresponding subsequence modulo Q is R. Input The input consists of at most 10 datasets. Each dataset is represented by a line containing four integers N, S, W, Q, and R, separated by spaces, where 1<=N<=10^5, 1<=S<=10^9, 1<=W<=10^9, Q is a prime number less than 10^9 and 0<=R<Q. The sequence a[0]...a[N-1] of length N is generated by the following code.

        int g = S;

        for (int i=0; i<N; i++) {

            a[i] = (g/7) % 10;

            if( g%2 == 0 ) { g = (g/2); }

            else { g = (g/2) ^ W; }

    }

    Note: the operators /, %, and ^ are the integer division, the modulo, and the bitwise exclusiveor, respectively. The above code is meant to be a random number generator. The intended solution does not rely on the way how the sequence is generated. The end of the input is indicated by a line containing five zeros separated by spaces. Output For each dataset, output the answer in a line.


    Sample Input

    3 32 64 7 0

    4 35 89 5 0

    5 555 442 3 0

    5 777 465 11 0

    100000 666 701622763 65537

    0 0 0 0 0 0


    Sample Output

    2

    4

    6

    3

    68530

    Hint In the first dataset, the sequence is 421. We can find two multiples of Q = 7, namely, 42 and 21. In the second dataset, the sequence is 5052, from which we can find 5, 50, 505, and 5 being the multiples of Q = 5. Notice that we don't count 0 or 05 since they are not a valid representation of positive integers. Also notice that we count 5 twice, because it occurs twice in different positions. In the third and fourth datasets, the sequences are 95073 and 12221, respectively. 


    题目大意

    给出一串十进制的数字,求当中有多少个子串所表示的数字模质数p的值为r

    思路

    如果一个子串为x[i]x[i+1]...x[j],则模p的值为(x[i]*10^(j-i)+x[i+1]*10^(j-i-1)+...+x[j]*10^0)%p,如果用f[n]表示(10^n)%p, t[n]表示原串的后n位模p的值。那么x[i]x[i+1]...x[j] %p=r等价于t[i]=(t[j-1]+r*10^(j-1))%p=(t[j-1]+r*f[j-1])%p,((a/b)%c=(a%(b*c)),这样以第i位开头的数字中符合要求的个数即为符合该式的j的个数(j>=i)。

    能够用map或哈希记录个数。m[x]表示符合(t[j]+r*f[j])%p=x的j的个数。

    做法

    按题目给的方法生成数字串,预处理求出f[n],再从右向左依次处理出t[n],将答案加上m[t[n]],再更新m[(t[n]+r*f[n])%p]就可以。

    说明

    当题目中的质数为2或5时须要特殊处理,由于10能够被2或5整除,不能再用10的幂次的形式取余。此时仅仅须要从高位向地位。不断统计最后一位模p为r的子串个数就可以,由于一个数除2或5的余数就等于最后一位模2或5.

    数字的首位不能为0,所以要注意仅仅有当前位不为0时才干更新答案。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int N=100005;
    long long a[N];
    long long f[N];
    void init(int n,long long s,long long w)
    {
    	long long g=s;
    	for (int i=1; i<=n; i++)
    	{
    		a[i]=(g/7)%10;
    		if (g%2==0) g=g/2; 
    		else g=(g/2)^w;
    	}
    }
    int main()
    {
    	int n,i;
    	long long s,w,q,r;
    	long long x,y,ans;
    	while (scanf("%d%lld%lld%lld%lld",&n,&s,&w,&q,&r)==5)
    	{
    		if (n==0 && s==0 && w==0 && q==0 && r==0) break;
    		init(n,s,w); ans=0;
    		if (q==2 || q==5)
    		{
    			s=0;
    			for (i=1; i<=n; i++){
    				if (a[i]!=0) s++;
    				if (a[i]%q==r) ans+=s;
    			}
    		}
    		if (q!=2 && q!=5)
    		{
    			f[n]=1;
    			for (i=n-1; i>=1; i--) f[i]=(f[i+1]*10)%q;
    			map<int,int> m;
    			m[r]=1;
    			x=0;
    			for (i=n; i>=1; i--)
    			{
    				x=(x+a[i]*f[i])%q;
    				if (a[i]!=0)ans+=m[x];
    				m[(r*f[i-1]+x)%q]++;
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    } 




  • 相关阅读:
    调用微信扫一扫接口
    Http错误代码解释
    php goto的用法
    Yii2.0-生成二维码实例
    飞鹅WiFi打印机配置,php调用接口
    HTML5 为什么只需要写 <!DOCTYPE HTML>?
    VueJs之 v-bind
    react 组件导出
    前端代码规范
    git与github的文件推送
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6901886.html
Copyright © 2020-2023  润新知