其他分享
首页 > 其他分享> > 1461 Poi2010 Beads(Bzoj2081 LOJ2427 LUOGU3498 提高+/省选-) 哈希 顺序逆序字串映射关系 STL map映射容器使用

1461 Poi2010 Beads(Bzoj2081 LOJ2427 LUOGU3498 提高+/省选-) 哈希 顺序逆序字串映射关系 STL map映射容器使用

作者:互联网

总目录

在线测评地址(ybt)

在线测评地址(LOJ)

在线测评地址(LUOGU)

ybt测试点30运行超时   LOJ AC   LUOGU AC

在浩瀚的题海中,不追求ybt所有测试点的通过,此题就此别过。

ybt

未通过

测试点结果内存时间
测试点1答案正确632KB2MS
测试点2答案正确636KB2MS
测试点3答案正确632KB1MS
测试点4答案正确632KB1MS
测试点5答案正确640KB1MS
测试点6答案正确644KB2MS
测试点7答案正确632KB1MS
测试点8答案正确632KB1MS
测试点9答案正确648KB1MS
测试点10答案正确652KB2MS
测试点11答案正确644KB2MS
测试点12答案正确640KB1MS
测试点13答案正确684KB2MS
测试点14答案正确648KB2MS
测试点15答案正确1612KB24MS
测试点16答案正确2176KB42MS
测试点17答案正确1204KB13MS
测试点18答案正确2560KB55MS
测试点19答案正确1348KB21MS
测试点20答案正确4524KB132MS
测试点21答案正确2060KB50MS
测试点22答案正确5508KB178MS
测试点23答案正确2412KB66MS
测试点24答案正确8440KB330MS
测试点25答案正确3456KB64MS
测试点26答案正确14304KB684MS
测试点27答案正确5612KB54MS
测试点28答案正确17236KB867MS
测试点29答案正确6624KB123MS
测试点30运行超时19448KB1000MS

LOJ

LUOGU

困扰了许久的问题,笔算就解决了,如下。

样例中,k=4,分成5个字串

(1,1,1,2),(2,2,3,3),(3,1,2,3),(3,1,2,2),(1,3,3,2)
中的
(3,1,2,3),(1,3,3,2)是同一子串吗?
不是 同一子串。
请注意题干:子串都是可以反转的。

因为反转:
(3,1,2,3)同一子串是(3,2,1,3)



n=200000,需要比较子串的次数,编程如下:

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n,cnt=0,i;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		cnt+=n/i;
	printf("cnt=%d\n",cnt);
	return 0;
} 

对应的输入输出数据如下:

200000
cnt=2472113

不会超时,放心了。

该题的难点在于找出字串,与反转字串的坐标映射关系。

字串总长度len
字串的位置区间[x,y]
对应的反转字串的位置区间[len-(y-1),len-(x-1)]

推导如下:

顺序    123456789
字串    123456789
反转字串987654321

字串总长度9
字串中的4567对应顺序区间[4,7]
反转字串中的7654对应的顺序区间[3,6]

字串的位置4,对应反转字串的位置6,换算关系9-(4-1)=6
字串的位置7,对应反转字串的位置3,换算关系9-(7-1)=3

字串总长度len
字串的位置区间[x,y]
对应的反转字串的位置区间[len-(y-1),len-(x-1)]

验证如下
字串中的1234对应顺序区间[1,4]
反转字串中的4321对应的顺序区间[9-(4-1),9-(1-1)]即[6,9]


找大于200000的质数,上线性筛

#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
int prime[maxn],tot,b[maxn];
void linear(int x){
	int i,j;
	for(i=2;i<=x;i++)b[i]=0;
	for(i=2;i<=x;i++){
		if(b[i]==0)prime[++tot]=i;
		for(j=1;j<=tot&&prime[j]*i<=x;j++){
			b[prime[j]*i]=1;
			if(i%prime[j]==0)break;
		}
	}
}
int main(){
	int x,i;
	scanf("%d",&x);
	linear(x);
	for(i=tot;i>=1;i--)
		if(prime[i]>=200000)printf("%d ",prime[i]);
	return 0;
} 

上述代码对应的输入输出数据:

200008
200003

找到质数200003

想开个数组,去重,但一看ULL范围,不可行,还是要借助STL,印象中可以借助set还是map,没用过,那就现学呗。

研究了,发现map好用,可以以局部变量的形式使用,免去了自主初始化。

ybt测试点30运行超时   LOJ AC   LUOGU AC 代码如下:

#include <bits/stdc++.h>
#define maxn 200010
#define B 200003
#define ULL unsigned long long
using namespace std;
int a[maxn],b[maxn],N,c[maxn],pos[maxn]; 
ULL ah[maxn],bh[maxn],n[maxn];
int main(){
	int i,j,k,xa,ya,aval,bval,xb,yb,v,mx=-1,kn=0;
	scanf("%d",&N);
	for(i=1;i<=N;i++){
		scanf("%d",&a[i]);//顺序存储 
		b[N-i+1]=a[i];//逆序存储 
	}
	n[0]=1;
	for(i=1;i<=N;i++)n[i]=n[i-1]*B;
	ah[0]=0,bh[0]=0;
	for(i=1;i<=N;i++){
		ah[i]=ah[i-1]*B+a[i];
		bh[i]=bh[i-1]*B+b[i]; 
	} 
	for(k=1;k<=N;k++){
		map<ULL,int> mp;
		v=0;
		for(j=1;j+k-1<=N;j+=k){//j代表初始位置,j+k-1代表末了位置 
			xa=j,ya=j+k-1;
			aval=ah[ya]-ah[xa-1]*n[ya-(xa-1)];
			xb=N-(ya-1),yb=N-(xa-1);
			bval=bh[yb]-bh[xb-1]*n[yb-(xb-1)];
			if(mp[aval]==0)mp[aval]=++v,mp[bval]=v;//顺序子串,逆序子串 效果等同 
		}
		c[k]=v;
		mx=max(mx,v);
	}
	for(k=1;k<=N;k++)
		if(c[k]==mx)++kn,pos[kn]=k;
	printf("%d %d\n",mx,kn);
	printf("%d",pos[1]);
	for(i=2;i<=kn;i++)printf(" %d",pos[i]);
	return 0;
}

该题除了翻阅STL map知识外,未查阅任何资料,编码全部独立完成。耗时半天。

提高+/省选-   需要补充的知识是 STL map的使用

标签:Bzoj2081,Beads,映射,测试点,int,maxn,字串,答案,正确
来源: https://blog.csdn.net/mrcrack/article/details/122002624