题目:
1.SEVERINA
【题目描述】
告诉一个文本串和N个模式串,要求文本串由若干可以重复的模式串首尾相接而成的方案数模1 337 377。
【输入格式】
第一行为文本串。
第二行为一个整数N,表示有N个模式串。以下N行,每行一个模式串,任意两个模式串不相同,且不存在其它任何字符。文本串和模式串都是小写字母。
【输出格式】
方案数模1337377。
【输入样例1】
abcd
4
a
b
cd
ab
【输出样例1】
2
【输入样例2】
afrikapaprika
4
afr
ika
pap
r
【输出样例2】
1
【输入样例3】
ababababababababababababababababababababab
3
a
b
ab
【输出样例3】
759775
【数据范围】
1<=N<=4 000,文本串长不超过300 000,模式串长不超过100。
2.组装
【题目描述】
数轴上有m个生产车间可以生产零件。一共有n种零件,编号为1~n。第i个车间的坐标为xi,生产第pi种零件(1<=pi<=n)。你需要在数轴上的某个位置修建一个组装车间,把这些零件组装起来。为了节约运输成本,你需要最小化cost(1)+cost(2)+…+cost(n),其中cost(x)表示生产第x种零件的车间中,到组装车间距离的平方的最小值。
【输入格式】
输入第一行为两个整数n, m,即零件的种类数和生产车间的个数。以下m行每行两个整数xi和pi(1<=pi<=n)。输入按照生产车间从左到右的顺序排列(即xi<=xi+1。注意车间位置可以重复)。输入保证每种零件都有车间生产。
【输出格式】
输出仅一行,即组装车间的最优位置(可以和某个生产车间重合),四舍五入保留四位小数。输入保证最优位置惟一。
【输入输出样例】
assemble.in |
assemble.out |
3 5 -1 3 0 1 2 3 4 2 5 2 |
2.0000 |
assemble.in |
assemble.out |
4 8 -10 2 -8 1 -5 1 -1 3 3 4 4 3 6 2 9 4 |
0.7500 |
【数据范围】
编号 |
1-4 |
5-10 |
n |
<=15 |
<=10000 |
m |
<=25 |
<=100000 |
xi |
<=100 |
<=100,000 |
3.探险
【题目描述】
牙神率领一支探险队乘坐从倍喜那里借来的银色面包车去乡下探险。
不幸的是,面包车的油箱撞上地上的石头后漏了,现在他们开一单位长度需要消耗一单位油(原本的消耗加上漏的等于一单位),他们只能停了下来做打算。
他们决定走直线公路去最近的城镇修车。目前他们还剩P单位油,从他们所在的地方到城市的距离为L单位长度,直线公路上有N个小型加油站,每个地方有Wi的油可以加。由于加油很慢,他们又很心急,所以牙神下令让你帮忙计算一个加油次数最少的并且能到城市的停站方案。
注意:没有油的时候就不能继续前行了。
【输入文件】
第一行一个整数N。
接下来N行,每行两个整数Di,Wi,表示这个加油站到城镇的距离和油量。
第N+2行两个整数L,P。
【输出文件】
仅一行,表示答案,如果不能到达,那么输出”-1”
【样例输入】
4
4 4
5 2
15 10
11 5
25 10
【样例输出】
2
【样例解释】
开10单位长度恰好到达3号站得到10单位油,然后再开4公里得到4号站的5单位油,然后直接开到城镇即可。
【数据规模】
对于100%的数据 N<=10000,Wi<=100,Di<=L<=1000000,P<=1000000
题解:
t1:首先考虑暴力dp,f[i]表示前i位匹配数,很显然是n^2L的算法
可以用hash优化dp,复杂度降为nl
最后:字母树
字母树优化至o(L)
代码:
#include<bits/stdc++.h> using namespace std; const int N=1000005; char str[105],z[N],c; int n,m,top=1,ans1,flag[N]; struct node { int ne[26],sum; }f[N]; void newone(int a) { memset(f[a].ne,-1,sizeof(f[a].ne)); f[a].sum=0; } void build(char str[]) { int p=0; for (int i=0;str[i];i++) { int x=str[i]-'a'; if (f[p].ne[x]==-1) { f[p].ne[x]=top; newone(top); top++; } p=f[p].ne[x]; } f[p].sum++; } int ans(int x,int add) { int p=0,int1; for (int i=0;i<1000;i++) { int1=z[x]-'a'; p=f[p].ne[int1]; if (p==-1) return 0; if (f[p].sum>0) { flag[x]+=add; flag[x]=flag[x]%1337377; } x++; } return f[p].sum; } int main() { freopen("severina.in","r",stdin); freopen("severina.out","w",stdout); scanf("%s",z+1); scanf("%d",&m); newone(0); for (int i=1;i<=m;i++) { scanf("%s",&str); build(str); } n=strlen(z+1); flag[0]=1; for (int i=0;i<=n;i++) { flag[i]=flag[i]%1337377; if (flag[i]>0)ans(i+1,flag[i]); } printf("%d",flag[n]); return 0; }
t2:本卷中最难的一题。
考虑暴力枚举每一种零件由哪一些机器制造,时间复杂度:o(c1c2c3...cm)
优化:
每一种机器先由第一个制造,在一个个往后移动
具体看
http://www.cnblogs.com/jianglangcaijin/p/4204478.html
代码:
#include<cstring> #include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int N=100005; double aa,bb,ans,fmin,x[N],y; int c[N],r[N],count1[N],n,m,n1; struct xx { double num; int next; }z[N]; bool cmp(xx a,xx b) { return a.num<b.num; } int read() { int x=0;char ch=getchar(); bool zositive=1; for (;!isdigit(ch);ch=getchar()) if (ch=='-')zositive=0; for (;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return zositive?x:-x; } int main() { freopen("assemble.in","r",stdin); freopen("assemble.out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++) { x[i]=read();c[i]=read(); if(!r[c[i]]) { aa+=x[i]; bb+=x[i]*x[i]; } else { count1[i]=r[c[i]]; z[++n1].num=(x[i]+x[r[c[i]]])/2; z[n1].next=i; } r[c[i]]=i; } sort(z+1,z+n1+1,cmp); ans=y=aa/n; fmin=bb-2*aa*y+y*y*n; for(int i=1;i<=n1;i++) { bb-=x[count1[z[i].next]]*x[count1[z[i].next]]; aa-=x[count1[z[i].next]]; bb+=x[z[i].next]*x[z[i].next]; aa+=x[z[i].next]; y=aa/n; if (fmin>bb-2*aa*y+y*y*n) { fmin=bb-2*aa*y+y*y*n; ans=y; } } printf("%.4lf",ans); return 0; }
t3:堆优化,其实o(n^2)大暴力也可以
注意是到终点的距离
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=100005; int f[N],ff[N],p,l,n,a[N],b[N]; void up(int x) { if (x==1)return; if (f[x]>f[x/2]) { swap(f[x],f[x/2]); up(x/2); } } void down(int x) { int i=x; if (x*2<=l&&f[i]<f[x*2])i=x*2; if (x*2<l&&f[i]<f[x*2+1])i=x*2+1; if (i!=x) { swap(f[i],f[x]); down(i); } } int cmp(int x,int y) { return a[x]<a[y]; } int main() { freopen("exp.in","r",stdin); freopen("exp.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]); scanf("%d%d",&a[n+1],&p); for (int i=1;i<=n;i++)a[i]=a[n+1]-a[i]; for (int i=1;i<=n;i++)ff[i]=i; sort(ff+1,ff+n+1,cmp); ff[n+1]=n+1; n++; int q=p,ans=0; for (int i=1;i<=n;i++) { q=q-a[ff[i]]+a[ff[i-1]]; while (q<0) { ans++; if (ans==i) { puts("-1"); return 0; } q+=f[1]; f[1]=f[l--]; down(1); } f[++l]=b[ff[i]]; up(l); } printf("%d",ans); return 0; }