模拟试题一

题目名称

符文之语 

最接近神的人 

古代人的难题 

宝物筛选 

提交程序名

chars

sophist

puzzle

treasure

输入文件名

chars.in

sophist.in

puzzle r.In

treasure.in

输出文件名

chars.out

sophist.out

puzzle.out

treasure.out

空间限制

50MB

50MB

50MB

50MB

时间限制

1s

1s

1s

1s

各题测试点数

10

10

10

10

各测试点分值

10

10

10

10

 

故事背景:

传说中珠穆朗玛峰下有座古代人修建的神庙,神庙的地下室里有古代王室的遗产。但数

千年来从未有人到达过……探险者小FF一直梦想成为世界上最富有的人和最杰出的探险家并被永载史册。在证明了这个洞确实存在后,小 FF做好了充足准备,来到了神庙。

 

试题一:符文之语(chars.pas/c/cpp)

 

【题目描述】

当小 FF来到神庙时,神庙已经破败不堪了。但神庙的中央有一个光亮如新的石台。小 FF走近石台,发现石台上有一个数串,而数串的上方刻着一串古老的符文之语。精通古符文之语的小 FF不费吹灰之力就读懂了文章的意思,其大意是:对于石台上的一串数字,你可以在适当的位置加入乘号(设加了 k个,当然也可不加,即分成k+1个部分),设这k+1个部分的乘积(如果k=0,则乘积即为原数串的值)对m的余数(即 mod m)为 x;现求 x能达到的最小值及该情况下k的最小值,以及 x能达到的最大值及该情况下的 k的最小值(可以存在 x的最小值与最大值相同的情况)。

小 FF还知道,如果他找到了正确的答案,那么就可以通往神庙的下层了。但这个问

题似乎不太好解决,小 FF就找到了你,并答应找到财宝以后和你二八分(当然你拿二……)。

【输入格式】

第一行为数串,且数串中不存在 0;

第二行为 m.

【输出格式】

四个数,分别为 x的最小值和该情况下的 k,以及 x的最大值和该情况下的 k,相邻

两个数之间用一个空格隔开。

【输入样例】

4421

22

【输出样例】

0  1  21  0

【数据范围】

对于 30%的数据: 2 <=字符串长度 L<=50.

对于100%的数据: 2 <=字符串长度 L<=1000;

2<=m<=50.

 

#include<cstdio>
#include<iostream>
#include<cstring>
#define oo 1147483647
using namespace std;
int num[1010][1010];
int f[1010][50];
char a[1010],s[1010];
int len,i,j,k,m;
int main()
{
    freopen("chars.in","r",stdin);
    freopen("chars.out","w",stdout);
    scanf("%s\n",a);
    scanf("%d\n",&m);
    len=strlen(a);
    for (i=0;i<len;i++) s[i+1]=a[i];
    for (i=1;i<=len;i++)
    for (j=i;j<=len;j++)
      num[i][j]=(num[i][j-1]*10+s[j]-48)%m;
    memset(f,127,sizeof(f));
    f[0][1]=0;
    for (i=1;i<=len;i++)
      for (j=1;j<=i;j++)
        for (k=0;k<m;k++)
          f[i][(k*num[j][i])%m]<?=f[j-1][k]+1;
    for (i=0;i<m;i++)
    {
        if (f[len][i]<oo)
        {
                         printf("%d %d ",i,f[len][i]-1);
                         break;
        }
    }
    for (i=m-1;i>=0;i--)
    {
        if (f[len][i]<oo)
        {
                         printf("%d %d",i,f[len][i]-1);
                         break;
        }
    }
    return 0;
}

 

试题二:最接近神的人(sophist/pas/c/cpp)

 

【题目描述】

     破解了符文之语,小 FF开启了通往地下的道路。当他走到最底层时,发现正前方

有一扇巨石门,门上雕刻着一副古代人进行某种活动的图案。而石门上方用古代文写着“神

的殿堂“。小 FF猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……

 

仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明

的。而最聪明的人往往通过一种仪式选拔出来。仪式大概是指,即将隐退的智者为他的候

选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素。而

用最少的交换次数使原序列变成不下降序列的人即是下一任智者。

小 FF发现门上同样有着 n个数字。于是他认为打开这扇门的秘诀就是找到让这个序

列变成不下降序列所需要的最小次数。但小 FF不会……只好又找到了你,并答应事成之后

与你三七分……

【输入格式】

第一行为一个整数 n,表示序列长度

第二行为 n个整数,表示序列中每个元素。

【输出格式】

一个整数 ans,即最少操作次数。

 

【输入样例】

4

2 8 0 3

【输出样例】

3

样例说明:开始序列为 2 80 3,目标序列为 0  2  3  8,可进行三次操作得目标序列:

1.Swap(8,0): 2  0  8  3

2.Swap(2, 0): 0  2  8  3

3.Swap(8, 3): 0  2  3  8

【数据范围】

对于 30%的数据 1<= n <= 10^4.

对于 100%的数据 1 <= n <= 5*10^5;

-maxlongint <= A[i ]<= maxlongint

 

#include<fstream>
#include<cstdlib>
#include<cstring>
#define maxn 1000010
using namespace std;
ifstream cin("sophist.in");
ofstream cout("sophist.out");
int n;
int a[maxn],b[maxn];
long long tot=0;
void msort(int l,int r)
{
     int i,j,m,k;
     if (l>=r) return;
     m=(l+r)>>1;
     msort(l,m);
     msort(m+1,r);
     i=l;k=l;j=m+1;
     do
     {
                   if (a[i]>a[j])
                   {
                                 tot+=m-i+1;
                                 b[k]=a[j];
                                 k++;j++;
                   }else {b[k]=a[i];k++;i++;}
     }while (i<=m&&j<=r);
     while (i<=m) 
     {
           b[k]=a[i];
           k++;
           i++;
     }
     while (j<=r) 
     {
           b[k]=a[j];
           k++;
           j++;
     }
     for (i=l;i<=r;i++) a[i]=b[i];
}
int main()
{
    cin>>n;
    for (int i=1;i<=n;i++) cin>>a[i];
    msort(1,n);
    cout<<tot<<endl;
    return 0;
}

 

试题三:古代人的难题(puzzle.pas/c/cpp)

 

【题目描述】

门打开了,里面果然是个很大的厅堂。但可惜厅堂内除了中央的一张羊皮纸和一根

精致的石笔,还有周围几具骷髅外什么也没有。难道这就是王室的遗产?小 FF不信,他

仔细阅读了羊皮纸上的内容后发现,里面书写的古代人一直没能解出的难题,解除这道题

目的人只要将答案用石笔写到这张羊皮纸上就能到达王室的宝藏室了。而当小FF拿起石笔

后,刚刚打开的巨石门突然关上了。这时小 FF意识到原来那几具骷髅是在他之前到这里

的冒险者,恐怕是因为没能破解这道题而困死在这里了。小 FF越想越害怕,急忙联系到

了你,为了能保命,他甚至愿意和你五五分……看来你不得不再次帮他了。羊皮纸上的问

题如下:已知 x, y为整数,且满足以下两个条件:

1. x, y ∈[1..k],且 x,y,k ∈Z;

2.(x^2 –xy – y^2)^2 =1

给你一个整数 k,求一组满足上述条件的x, y并且使得 x^2 +y^2的值最大。

当小FF得到答案后,用石笔将答案书写在羊皮纸上,那么就能到达王室的遗产所

在地了。

 

【输入格式】

一个整数 k

【输出格式】

输出文件仅一行,两个整数;两个整数分别表示 x和 y。x, y之间用一个空格隔开。

【输入样例】

1995

【输出样例】

1597  987

【数据范围】

对于 30%的数据: 2<=k<=10^4.

对于 100%的数据: 2<=k<=10^18.

 

#include<fstream>
#include<cstdlib>
#include<cstring>
using namespace std;
ifstream cin("puzzle.in");
ofstream cout("puzzle.out");
long long n;
long long a[3][3],b[3][3],c[3][3];
long long num1,num2;
int main()
{
    int i,j,k;
    cin>>n;
    a[1][1]=1;
    a[1][2]=1;
    a[2][1]=1;
    a[2][2]=0;
    memcpy(b,a,sizeof(a));
    while (b[1][1]+b[2][1]<n)
    {
          memset(c,0,sizeof(c));
          for (i=1;i<3;i++)
          for (j=1;j<3;j++)
          for (k=1;k<3;k++)
          c[i][j]=c[i][j]+a[i][k]*b[k][j];
          memcpy(b,c,sizeof(c));
    }
    num1=b[1][1];
    num2=b[2][1];
    cout<<num1<<" "<<num2<<endl;
    return 0;
}

 

试题四:宝物筛选(Treasure.pas/c/cpp)

 

【题目描述】

终于,破解了千年的难题。小FF 找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF 可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF 的采集车似乎装不下那么多宝物。看来小FF 只能含泪舍弃其中的一部分宝物了……小FF 对洞穴里的宝物进

行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始

了宝物筛选工作:小FF 有一个最大载重为W 的采集车, 洞穴里总共有n 种宝物的,每种宝物的价值为v[i], 重量为w[i], 每种宝物有m[i]件。小FF 希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。

【输入格式】

第一行为2 整数N 和W,分别表示宝物种数和采集车的最大载重。

接下来n 行每行三个整数,其中第i 行第一个数表示第i 类品价值, 第二个整数表示一件该类物品的重量,第三个整数为该类物品数量。

【输出格式】

输出仅一个整数ans, 表示在采集车不超载的情况下收集的宝物的最大价值。

【输入样例】

4 20

3 9 3

5 9 1

9 4 2

8 1 3

【输出样例】

47

【数据范围】

对于30%的数据: n <= Σm[i] <= 10^4; 0 <= W <=10^3.

对于100%的数据: n <= Σm[i] <=10^5; 0<= W <=4 * 10^4;

1 <= n <= 100.

 

#include<cstdio>
#include<iostream>
using namespace std;
int n,v;
int f[100010];
int w[100010],s[100010];
int m,a,b;
int i,j,k;
int main()
{
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    scanf("%d%d\n",&n,&v);
    j=0;
    for (i=1;i<=n;i++)
    {
        scanf("%d%d%d\n",&b,&a,&m);
        k=0;
        while ((m-(1<<(k+1))+1)>0)
        {
              w[++j]=(a*(1<<k));
              s[j]=(b*(1<<k));
              k++;
        }
        w[++j]=a*(m-(1<<k)+1);
        s[j]=b*(m-(1<<k)+1);
    }
    for (i=1;i<=j;i++)
    for (k=v;k>=w[i];k--)
    {
        f[k]>?=f[k-w[i]]+s[i];
    }
    printf("%d\n",f[v]);
    return 0;
}