2016"百度之星" - 资格赛(Astar Round1)

来源:互联网 发布:国债收益率 知乎 编辑:程序博客网 时间:2024/05/18 03:50

Problem A

 
 Accepts: 599
 
 Submissions: 5110
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
Problem Description

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

H(s)=\prod_{i=1}^{i\leq len(s)}(S_{i}-28)\ (mod\ 9973)H(s)=i=1ilen(s)(Si28) (mod 9973)

S_{i}Si代表 S[i] 字符的 ASCII 码。

请帮助度熊计算大字符串中任意一段的哈希值是多少。

Input

多组测试数据,每组测试数据第一行是一个正整数NN,代表询问的次数,第二行一个字符串,代表题目中的大字符串,接下来NN行,每行包含两个正整数aabb,代表询问的起始位置以及终止位置。

1\leq N\leq 1,0001N1,000

1\leq len(string)\leq 100,0001len(string)100,000

1\leq a,b\leq len(string)1a,blen(string)

Output

对于每一个询问,输出一个整数值,代表大字符串从 aa 位到 bb 位的子串的哈希值。

Sample Input
2ACMlove20151 118 101testMessage1 1
Sample Output
68919240

88

解:思路很简单,就是把1-n的乘积放在一个dp数组里面,最后ans=dp[r]/dp[l-1] %mod.当然乘法逆元肯定是要用到的。

#include<stdio.h>#include<string.h>#include<string>#include<iostream>#include<algorithm>using namespace std;#define LL long longconst LL maxm=1e5+10;const LL mod=9973;string s;LL dp[maxm];LL quickmod(LL a,LL b){    LL sum=1;    while(b)    {        if(b&1)            sum=(sum*a)%mod;        b>>=1;        a=(a*a)%mod;    }    return sum;}int main(){    LL n;    while(scanf("%I64d",&n)!=EOF)    {       cin>>s;        dp[0]=1;        for(LL i=1; i<=s.length(); i++)        {            dp[i]=(dp[i-1]*(s[i-1]-28))%mod;        }       LL l,r;        for(LL i=0; i<n; i++)        {            scanf("%I64d%I64d",&l,&r);            if(l>r)            {                swap(l,r);            }            printf("%I64d\n",(dp[r]*(quickmod(dp[l-1],mod-2)%mod))%mod);        }    }    return 0;}

Problem B

 
 Accepts: 728
 
 Submissions: 2903
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
Problem Description

度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列。

Input

这里包括多组测试数据,每组测试数据包含一个正整数NN,代表全1序列的长度。

1\leq N \leq 2001N200

Output

对于每组测试数据,输出一个整数,代表由题目中所给定的全1序列所能形成的新序列的数量。

Sample Input
135
Sample Output
138
Hint
如果序列是:(111)。可以构造出如下三个新序列:(111), (21), (12)。
解:推了一下,就是个菲薄垃圾数列,dp[i]=dp[i-1]+dp[i-2].这里我用的是JAVA过的,比较简单。不过,坑点就是在于当n=0时,输出换行。
import java.util.Scanner;import java.math.BigInteger;public class Main {    public static BigInteger[]dp=new BigInteger[205];    public static void main(String[] args) {        // TODO Auto-generated method stub        Scanner cin=new Scanner(System.in);        //int n=cin.nextInt();        Init();        while(cin.hasNext())        {            int n=cin.nextInt();            if(n>=1&&n<=200)            {                System.out.print(dp[n]);            }            System.out.println();        }                    }    public static void Init()    {        dp[1]=new BigInteger("1");        dp[2]=new BigInteger("2");        for(int i=3;i<=201;i++)        {            dp[i]=dp[i-1].add(dp[i-2]);        }    }}

Problem D

 
 Accepts: 860
 
 Submissions: 2290
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
Problem Description

度熊所居住的 D 国,是一个完全尊重人权的国度。以至于这个国家的所有人命名自己的名字都非常奇怪。一个人的名字由若干个字符组成,同样的,这些字符的全排列的结果中的每一个字符串,也都是这个人的名字。例如,如果一个人名字是 ACM,那么 AMC, CAM, MAC, MCA, 等也都是这个人的名字。在这个国家中,没有两个名字相同的人。

度熊想统计这个国家的人口数量,请帮助度熊设计一个程序,用来统计每一个人在之前被统计过多少次。

Input

这里包括一组测试数据,第一行包含一个正整数NN,接下来的NN 行代表了 NN 个名字。NN 不会超过1,000,0041,000,004,他们的名字不会超过40位.

Output

对于每输入的一个人名,输出一个整数,代表这个人之前被统计了多少次。

Sample Input
5ACMMACBBAACMBAB
Sample Output
01021
解:大水题一道,排序一下,map一下,就完了
#include<stdio.h>#include<string.h>#include<math.h>#include<iostream>#include<string>#include<map>#include<queue>#include<algorithm>using namespace std;#define LL __int64const LL maxm=1e5+10;const LL mod=9973;char s[maxm];map<string,int>q;int dp[maxm];void Init()//素数线性筛{    int vis[maxm];    int isprime[maxm];    int prime[maxm];    int cnt=0;    memset(vis,0,sizeof(vis));    memset(isprime,0,sizeof(isprime));    memset(prime,0,sizeof(prime));    for(int i=2; i<=maxm; i++)    {        if(!vis[i])        {            prime[cnt++]=i;            vis[i]=1;        }        for(int j=0; j<cnt&&i*prime[j]<maxm; j++)        {            vis[i*prime[j]]=1;        }    }    for(int i=0; i<cnt; i++)    {        isprime[prime[i]]=1;    }}int POW(int n,int k)//n的k次方{    int sum=1;    for(int i=1; i<=k; i++)    {        sum*=n;    }    return sum;}int quickmod(int a,int b,int mod)//快速{    int ans=1;    a=a%mod;    while(b)    {        if(b&1)            ans=(ans*a)%mod;        b>>=1;        a=(a*a)%mod;    }    return ans;}int main(){    int n;    scanf("%d",&n);    q.clear();    for(int i=0; i<n; i++)    {        scanf("%s",s);        int len=strlen(s);        sort(s,s+len);        printf("%d\n",q[s]++);    }    return 0;}


1 0