第七届(2001)分区联赛复赛试题
(提高组)
内存限制128MB,时限1秒
第一题:一元三次方程求解
(p1.pas p1.in p1.out)
问题描述
有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1,x2)之间一定有一个根。
样例
输入:1 -5 -4 20
输出:-2.00 2.00 5.00
第二题:数的划分
(p2.pas/c/cpp p2.in p2.out)
问题描述
将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。例如:n=7,k=3,下面三种分法被认为是相同的。1,1,5; 1,5,1; 5,1,1;问有多少种不同的分法。
输入:n,k (6<n<=200,2<=k<=6)
输出:一个整数,即不同的分法。
样例
输入: 7 3
输出:4 {四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;}
第三题:统计单词个数
(p3.pas/c/cpp p3.in p3.out)
问题描述
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
输入格式:输入数据放在文本文件p3.in中,其格式如下:第一行为一个正整数(0<n<=5)表示有n组测试数据每组的第一行有二个正整数(p,k),p表示字串的行数;k表示分为k个部分。接下来的p行,每行均有20个字符。再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)接下来的s行,每行均有一个单词。
输出格式:结果输出至屏幕,每行一个整数,分别对应每组测试数据的相应结果。
样例
输入:
1
1 3
thisisabookyouareaoh
4
is
a
ok
sab
输出: //说明:(不必输出)
7 // this/isabookyoua/reaoh
第四题:CAR的旅行路线
(p4.pas/c/cpp p4.in p4.out)
问题描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
x |
y |
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务:找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入文件:输入文件名p4.in
输 出:p4.out(输出最小费用,小数点后保留1位。)
输入格式:第一行为一个正整数n(0<=n<=10),表示有n组测试数据。每组的第一行有四个正整数s,t,A,B。S(0<S<=100)表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。
输出格式:共有n行,每行一个数据对应测试数据。
样例
输入
1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
输出:
47.5
这套题已经没有太大价值了,历史太久远。第一次测300分,因为第三题有点没有理解清楚题意。
1、2、4题没有太多讨论的价值,直接贴上代码。
另外4题,这种题还是有做的价值的,这种题是必过的,但是不一定正式考试能够足够冷静,这种题只要不慌乱,就能拿全!所以要训练自己的细致和严谨,因为正式考试不可能像平时这般轻松,平常需要更加地细心,正式考试才能不乱。
#include <cstdio>
double a,b,c,d;
double eps = 1e-11;
int main()
{
freopen("p1.in","r",stdin);
freopen("p1.out","w",stdout);
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
//if (abs(-a*1000000+b*10000-c*100+d)<eps)
// printf("-100 ");
for (double x=-100.000-0.001;x<=100.000-0.001;x+=0.001)
{
double xx = x*x;
double xxx = xx*x;
double x2 = x+0.001;
double xx2 = x2*x2;
double xxx2 = xx2*x2;
double rs1 = (a*xxx+b*xx+c*x+d);
double rs2 = (a*xxx2+b*xx2+c*x2+d);
if (rs1<-eps&&rs2>eps || rs1>eps&&rs2<-eps)
printf("%.2lf ",x+0.0005);
}
return 0;
}
#include <cstdio>
long n,k;
long ans = 0;
void dfs(long u,long last,long sum)
{
if (u == k)
{
if (n-sum>=last)
ans ++;
return;
}
for (long i=last;i+sum<n+1;i++)
{
dfs(u+1,i,sum+i);
}
}
int main()
{
freopen("p2.in","r",stdin);
freopen("p2.out","w",stdout);
scanf("%ld%ld",&n,&k);
dfs(1,1,0);
printf("%ld",ans);
return 0;
}
#include <cstdio>
#include <cmath>
#include <string>
double dist[510];
double len[510][510];
bool used[510];
long x[510];
long y[510];
long t[110];
long n;
long tf;
long A;
long B;
long cnt;
long getint()
{
long rs=0;bool sgn=1;char tmp;
do tmp=getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=1;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void dijkstra(long u)
{
for (long i=0;i<n;i++)
{
dist[i] = len[u][i];
used[i] = false;
}
dist[u] = 0;
for (long l=1;l<n;l++)
{
double nearest=0x7f7f7f7f;
long k = -1;
for (long i=0;i<n;i++)
{
if (!used[i] && dist[i]<nearest)
{
nearest = dist[i];
k = i;
}
}
used[k] = true;
for (long i=0;i<n;i++)
if (!used[i] && dist[i]>dist[k]+len[k][i])
dist[i] = dist[k] + len[k][i];
}
}
int main()
{
freopen("p4.in","r",stdin);
freopen("p4.out","w",stdout);
long T = getint();
while (T --)
{
n = getint();
tf = getint();
A = getint();
B = getint();
cnt = -1;
for (long i=0;i<n;i++)
{
long x1,x2,x3,x4,y1,y2,y3,y4;
x1 = getint();y1 = getint();
x2 = getint();y2 = getint();
x3 = getint();y3 = getint();
cnt++;x[cnt] = x1;y[cnt] = y1;
cnt++;x[cnt] = x2;y[cnt] = y2;
cnt++;x[cnt] = x3;y[cnt] = y3;
x4 = x1+x2-x3;
y4 = y1+y2-y3;
if ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) != (x4-x3)*(x4-x3)+(y4-y3)*(y4-y3))
{
x4 = x2+x3-x1;
y4 = y2+y3-y1;
if ((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2) != (x4-x1)*(x4-x1)+(y4-y1)*(y4-y1))
{
x4 = x1+x3-x2;
y4 = y1+y3-y2;
}
}
cnt++;x[cnt] = x4;y[cnt] = y4;
t[i] = getint();
}
n *= 4;
for (long i=0;i<n;i++)
for (long j=i+1;j<n;j++)
{
if (j/4 == i/4)
len[i][j] = len[j][i] = sqrt(double((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])))*double(t[i/4]);
else
len[i][j] = len[j][i] = sqrt(double((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])))*double(tf);
}
double ans = 1e19;
A--;B--;
for (long i=A*4;i<A*4+4;i++)
{
dijkstra(i);
for (long j=B*4;j<B*4+4;j++)
if (dist[j] < ans)
ans = dist[j];
}
printf("%.1lf\n",ans);
}
return 0;
}
第三题还是值得一提。
每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th
这句话需要理解清楚,我就是卡在了这句话上。它的意思是同一位置不能多次作为首字母。而并不是说两个相同首字母的单词不能重复使用。
这样的话,就很简单了,因为预处理区间内最多的单词数,是一个固定的值,而不存在找最优。我们只需要贪心,以每一个位置为起点,能找到任意一个匹配的单词,就把g[i][j]加一。
动规部分很简单,都能非常容易地想出来。f[i][k] = max(f[j][k-1]+g[j+1][i])
需要注意的是,动规的初值,绝对不能小窥,我再一次错在了这里,以后再也不错这里了!!
很简单,比如[1,3]这个区间没有匹配的单词,而[3,4]有一个匹配的单词,如果不初始化为负无穷,则f[4][2]会是2,这当然是错的!因为f[3][1]实际上是无效状态。
#include <cstdio>
#include <string>
#define max(a,b) ((a)>(b)?(a):(b))
long getint()
{
long rs=0;bool sgn=1;char tmp;
do tmp=getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){sgn=0;tmp=getchar();}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
char word[10][210];
char str[210];
long g[210][210];
long f[210][50];
long len;
long n;
void pre(long l,long r)
{
for (long i=l;i<r+1;i++)
{
for (long j=1;j<n+1;j++)
{
if (i+word[j][0]-1<r+1)
{
bool ok = true;
for (long x=1;x<word[j][0]+1;x++)
{
if (str[i+x-1]!=word[j][x])
{
ok = false;
break;
}
}
if (ok)
{
g[l][r] ++;
break;
}
}
}
}
}
int main()
{
freopen("p3.in","r",stdin);
freopen("p3.out","w",stdout);
long T = getint();
while (T--)
{
memset(g,0,sizeof g);
memset(f,0,sizeof f);
long tmp = getint();
long K = getint();
len = tmp * 20;
for (long i=0;i<tmp;i++)
scanf("%s",str+i*20+1);
n = getint();
for (long i=1;i<n+1;i++)
{
word[i][0] = 0;
scanf("%s",word[i]+1);
while (word[i][++word[i][0]]);
word[i][0] --;
}
for (long i=1;i<len+1;i++)
for (long j=i;j<len+1;j++)
pre(i,j);
memset(f,0x80,sizeof f);
for (long i=1;i<len+1;i++)
f[i][1] = g[1][i];
for (long i=1;i<len+1;i++)
{
for (long j=1;j<i;j++)
{
for (long k=2;k<K+1;k++)
{
f[i][k] = max(f[i][k],f[j][k-1]+g[j+1][i]);
}
}
}
printf("%ld\n",f[len][K]);
}
return 0;
}