HDU 5685 Problem A(逆元)

版权声明:转载请说明出处:https://blog.csdn.net/hanyanwei123 https://blog.csdn.net/hanyanwei123/article/details/81632498

Problem A

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2241    Accepted Submission(s): 989


Problem Description
度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串。现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值。一个字符串的哈希值,由以下公式计算得到:

H(s)=ilen(s)i=1(Si28) (mod 9973) 位的子串的哈希值。
 

Sample Input
   
   
2
ACMlove2015
1 11
8 10
1
testMessage
1 1
 

Sample Output
   
   
6891
9240
88
 

Source
 

Recommend
liuyiding
 

题解:求s[a]到s[b]的哈希值之积,
注意∏符号,求积。若直接求a到b会超时,,想到求1到b的前缀积除以1到a的前缀积,因为取模不满足相除,这里通用求逆元来解决
解法一:(直接求逆元,打表)
解法二:(用扩展欧几里得算法)
两个代码放在一起了

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
const int mod = 9973;
int N;
int H[100000+5];
int inv[10000];
string s;
int a,b;
int exgcd(int A,int B,int &x,int &y){
    if(B==0){
        x=1;
        y=0;
        return A;
    }
    int d = exgcd(B,A%B,x,y);
    int temp=x;
    x=y;
    y=temp-A/B*y;
    return d;
}
int Inv(int A,int B){
    int x,y;
    int d = exgcd(A,B,x,y);
    x=(x%mod+mod)%mod;
    return x;
}
int main()
{
    inv[1]=1;
    //逆元打表
    for(int i=2;i<10000;i++){
        inv[i] =inv[mod%i]*(mod-mod/i)%mod;
    }
    while(scanf("%d",&N)!=EOF){
        cin >> s;
        int len=s.length();
        H[0]=1;
        for(int i=1;i<=len;i++){
            H[i]=(H[i-1]%mod)*((s[i-1]-28)%mod)%mod;

        }

        for(int i=1;i<=N;i++){
            scanf("%d %d",&a,&b);
            int sum=1,sum1=1,ans=1;
            ans=H[b];
            //解法一从表中求得逆元
            sum1=inv[H[a-1]]%mod;
            //exgcd得到
            sum=Inv(H[a-1],mod);
            printf("%d\n",((ans%mod)*(sum%mod))%mod);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hanyanwei123/article/details/81632498