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

本文介绍了使用字符串哈希解决度熊丢失单词序列的问题,并提供了一种统计具有奇特姓名的人口数量的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem A

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

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

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

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

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

Input

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

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

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

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

Output

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

Sample Input
2
ACMlove2015
1 11
8 10
1
testMessage
1 1
Sample Output
6891
9240

88

//逆元模板

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long 
#define N 100010
#define M 9973
using namespace std;
char s[N];
int sum[N];
ll ks(ll x,ll k)
{
	ll s=1;
	while(k)
	{
		if(k&1)
			s=(s*x)%M;
		x=x*x%M;
		k>>=1;
	} 
	return s%M;
}
int main()
{
	int t,n,m,i,j,k;
	while(scanf("%d",&n)!=EOF)
	{
		getchar();
		gets(s);
		int len=strlen(s);
		sum[0]=1;
		for(i=0;i<len;i++)
			sum[i+1]=sum[i]*(s[i]-28)%M;
		int a,b;
		while(n--)
		{
			scanf("%d%d",&a,&b);
			int x=sum[a-1];
			int y=sum[b];
			ll p=ks(x,M-2);
			ll ans=y*p%M;
			printf("%lld\n",ans);
		}
	}
	return 0;
} 
<div id="problem-info"><h1>Problem B</h1>		 <div class="problem-statistic"><span class="fa fa-check text-success"></span> Accepts: 2371		</div>		 <div class="problem-statistic"><span class="fa fa-bar-chart text-info"></span> Submissions: 8741		</div>		 <div><div class="problem-statistic"><span class="fa fa-clock-o"></span> Time Limit: 2000/1000 MS (Java/Others)			 </div>			 <div class="problem-statistic"><span class="fa fa-th-large"></span> Memory Limit: 65536/65536 K (Java/Others)			 </div>					 </div></div><div class="problem"><div class="problem-widget"><div class="problem-widget-title">Problem Description</div><div class="problem-widget-content markdown marked"><p>度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列。</p></div></div><div class="problem-widget"><div class="problem-widget-title">Input</div><div class="problem-widget-content markdown marked"><p>这里包括多组测试数据,每组测试数据包含一个正整数<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height: 0.68em;"></span><span class="strut bottom" style="height: 0.68em; vertical-align: 0em;"></span><span class="base textstyle uncramped"><span class="mord mathit" style="margin-right: 0.1em;">N</span></span></span></span>,代表全1序列的长度。</p><p><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mn>1</mn><mo>≤</mo><mi>N</mi><mo>≤</mo><mn>2</mn><mn>0</mn><mn>0</mn></mrow><annotation encoding="application/x-tex">1\leq N \leq 200</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height: 0.68em;"></span><span class="strut bottom" style="height: 0.81em; vertical-align: -0.13em;"></span><span class="base textstyle uncramped"><span class="mord">1</span><span class="mrel">≤</span><span class="mord mathit" style="margin-right: 0.1em;">N</span><span class="mrel">≤</span><span class="mord">2</span><span class="mord">0</span><span class="mord">0</span></span></span></span></p></div></div><div class="problem-widget"><div class="problem-widget-title">Output</div><div class="problem-widget-content markdown marked"><p>对于每组测试数据,输出一个整数,代表由题目中所给定的全1序列所能形成的新序列的数量。</p></div></div><div class="problem-widget"><div class="problem-widget-title">Sample Input</div><div class="problem-widget-content clipboard"><button class="copy" data-clipboard-target="#simple-input-data">Copy</button><pre id="simple-input-data">1
3
5

Sample Output
1
3
8

Hint
如果序列是:(111)。可以构造出如下三个新序列:(111), (21), (12)。
//大斐波那契数

<pre name="code" class="cpp"><pre name="code" class="cpp">#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int f[1005][1005];
void count(){
    f[1][0]=1;f[2][0]=1;
    int p,q,i,j,e;
    for(i=3;i<=1001;++i){
        p=0;
        for(j=0;j<1000;++j){
            f[i][j]=(f[i-1][j]+f[i-2][j]+p)%10;
            p=(f[i-1][j]+f[i-2][j]+p)/10;
        }
    }
}
int main()
{
    count();
    int n,t,i,k,j;
    while(scanf("%d",&k)!=EOF){k+=1;
        for(i=1000;i>=0;--i)
            if(f[k][i]!=0)break;
        for(j=i;j>=0;--j)
            printf("%d",f[k][j]);
        printf("\n");
    }
    return 0;
}



Problem D

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

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

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

Input

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

Output

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

Sample Input
5
ACM
MAC
BBA
ACM
BAB
Sample Output
0
1
0
2
1
//暴力

<pre name="code" class="cpp">#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	char str[50];
	int id,num;
}p[1000010];
char s[50];
int cmp(node s1,node s2)
{
	if(strcmp(s1.str,s2.str)==0)
		return s1.id<s2.id;
	if(strcmp(s1.str,s2.str)<0) 
	return true;
	return false;
}
int cmp1(node s1,node s2)
{
	return s1.id<s2.id;
}
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=0;i<n;i++)
		{
			scanf("%s",p[i].str);
			int l=strlen(p[i].str);
			sort(p[i].str,p[i].str+l);
			p[i].id=i;
			p[i].num=0;
		}
		sort(p,p+n,cmp);
		int cnt=0;
		strcpy(s,p[0].str);
		for(int i=1;i<n;i++)
		{
			
			if(strcmp(s,p[i].str)==0)
			{
				p[i].num=++cnt;
			}
			else
			{
				p[i].num=0;
				cnt=0;
				strcpy(s,p[i].str);
			}
		}
		sort(p,p+n,cmp1);
		for(int i=0;i<n;i++)
		printf("%d\n",p[i].num);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值