特长生模拟——16年东莞特长生考试

206 篇文章 0 订阅
127 篇文章 0 订阅

预测:100+100+100+100=400
实际:100+0+100+0=200
T2是小细节,T4是它题面跟标题的文件名不一+细节错误
唉,下次再这样剁手

T1,子数整数,题目大意:

对于一个五位数 a1a2a3a4a5,可将其拆分为三个子数: sub1=a1a2a3

sub2=a2a3a4

sub3=a3a4a5

例如,五位数 20207 可以拆分成 sub1=202

sub2=020(=20) sub3=207

现在给定一个正整数 K,要求你编程求出 10000(包括 10000)到 30000(包括 30000)之间所有满足下述条件的五位数,条件是这些五位数的三个子数 sub1,sub2,sub3 都可被 K 整除。
要求从小到大输出。不得重复输出或遗漏。如果无解,则输出“-1”。

题解:

直接枚举判断即可。

代码:

#include<iostream>
#include<cstdio>

using namespace std;

int k;

int main()
{
    scanf("%d",&k);
    int sum=0;
    for (int i=10000; i<=30000; i++)
        {
             int a1=i/100;
             int b1=i/10%1000;
             int c1=i%1000;
             if (a1%k==0 && b1%k==0 && c1%k==0) 
                 {
                    printf("%d\n",i);
                    sum++;
                 }
        }
    if (!sum) printf("%d\n",-1);
    return 0;
}

T2,游戏问题,题目大意:

“五四”青年节到了,某学校要举行一个游园活动,其中有一个这样的游戏: n 个同学(编号从 0 到 n-1)围坐一圈,按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号同学在第 0 号位置,第 1 号同学在第 1 号位置,„„,

依此类推。
游戏规则如下:每一轮第 0 号位置上的同学顺时针走到第 m 号位置,第 1号位置同学走到第 m+1 号位置,„„,依此类推,第 n − m 号位置上的同学走到第 0 号位置,第 n-m+1 号位置上的同学走到第 1 号位置,„„,第 n-1 号位置上的同学顺时针走到第 m-1 号位置。

现在,一共进行了 10^k 轮,请问 x 号同学最后走到了第几号位置。
对于 30% 的数据,0 < k < 7;
对于 80% 的数据, 0 < k < 10^7;
对于 100% 的数据,
1 < n <1,000,000
0 < m < n
1 ≤ x ≤ n
0 < k < 10^9

题解:

因为每进行N轮则回到原点,所以只需要进行10^K mod N轮即可,这里用快速幂然后模拟一下即可,垃圾快速幂

代码:

#include<iostream>
#include<cstdio>

using namespace std;

int n,m,x,k;

int ksm(int x,int y)
{
    int rp=0;
    while (y) 
    {
        if (y%2) 
           {
                if (!rp) rp=1;
                rp=(rp%n)*x%n;
           }
        y=y/2;
        x=(x%n)*x%n;
    }
    return rp;
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&x);
    int cp=ksm(10,k);
    for (int i=1; i<=cp; i++)
        {
             x=x+m;
             if (x>n-1) x=x-(n-1)-1;
        }
    printf("%d\n",x);
    return 0;
}

T3,字串距离,题目大意:

设有字符串 X,我们称在 X 的头尾及中间插入任意多个空格后构成的新字符
串为 X 的扩展串,如字符串 X 为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd □”和“abcb□cd□”都是 X 的扩展串,这里“□”代表空格字符。
如果 A1 是字符串 A 的扩展串,B1 是字符串 B 的扩展串,A1 与 B1 具有相 同的长度,那么我扪定义字符串 A1 与 B1 的距离为相应位置上的字符的距离总 和,而两个非空格字符的距离定义为它们的 ASCII 码的差的绝对值,而空格字 符与其他任意字符之间的距离为已知的定值 K,空格字符与空格字符的距离为 0。
在字符串 A、B 的所有扩展串中,必定存在两个等长的扩展串 A1、B1,使得 A1 与 B1 之间的距离达到最小,我们将这一距离定义为字符串 A、B 的距离。

请你写一个程序,求出字符串 A、B 的距离。

A、B 均由小写字母组成且长度均不超过 2000
1≤K≤100

题解:

f[i][j]表示A前i位B前j位匹配后的最小值。
则可以推出,
f[i][j]=
min(f[i-1][j]+k,f[i][j-1]+k,f[i-1][j-1] + 差值)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2005

using namespace std;

char u[N],v[N];
int f[N][N],k;

int abs(int aa)
{
    if (aa>0) return aa;
    return -aa;
}

int min(int aa,int bb)
{
    if (aa>bb) return bb;
    return aa;
}

int main()
{
    scanf("%s",&u);
    scanf("%s",&v);
    scanf("%d",&k);
    int u1=strlen(u),v1=strlen(v);
    for (int i=0; i<u1; i++) f[i+1][0]=(i+1)*k;
    for (int i=0; i<v1; i++) f[0][i+1]=(i+1)*k;
    for (int i=1; i<=u1; i++)
         for (int j=1; j<=v1; j++)
             {
                  f[i][j]=min(f[i][j-1],f[i-1][j])+k;
                  f[i][j]=min(f[i][j],f[i-1][j-1]+abs(u[i-1]-v[j-1]));                
             }  
    printf("%d\n",f[u1][v1]);
    return 0;
}

T4,村庄重建,题目大意:

B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。
给出 B 地区的村庄数 N,村庄编号从 0 到 N-1,和所有 M 条公路的长度,公路是双向的。并给出第 i 个村庄重建完成的时间 t[i],你可以认为是同时开始重建并在第 t[i]天重建完成,并且在当天即可通车。若 t[i]为 0 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 Q 个询问(x, y, t),对于每个询问你要回答在第 t 天,从村庄 x 到村庄 y 的最短路径长度为多少。如果无法找到从 x 村庄到 y 村庄的路径,经过若干个已重建完成的村庄,或者村庄 x 或村庄 y 在第 t 天仍未重建完成 ,则需要返回-1。

ti为非负整数
保证了 t[0] ≤ t[1] ≤ „ ≤ t[N – 1]。
对于 30%的数据,有 N≤50;
对于 30%的数据,有 t[i] = 0,其中有 20%的数据有 t[i] = 0 且 N>50;
对于 50%的数据,有 Q≤100;
对于 100%的数据,有 N≤200,M≤N*(N-1)/2,Q≤50000,所有输入数据涉及整数均不超过 100000

题解:

因为t[i]递增且询问中的时间也是递增的,所以我们每次进行回答询问的时候,以被新解封的村庄为中点去做floyd即可,然后看村庄是否都解封,或者相通,然后判断输出
我一开始是错在f[i][i]=0,因为我忘了将自身跟自身设为0。。。

代码:

#include<iostream>
#include<cstdio>
#define INF 2333333
#define N 205

using namespace std;

int u,v,w,n,m,q,f[N][N],t[N];

int min(int aa,int bb)
{
    if (aa>bb) return bb;
    return aa;
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=0; i<=n-1; i++)
        {
             for (int j=0; j<=n-1; j++) f[i][j]=INF;
             f[i][i]=0;
        }
    for (int i=0; i<=n-1; i++) scanf("%d",&t[i]);
    for (int i=1; i<=m; i++)
        {
             scanf("%d%d%d",&u,&v,&w);
             f[u][v]=w;
             f[v][u]=w;
        }
    int k=-1;
    scanf("%d",&q);
    for (int l=1; l<=q; l++)
        {
             scanf("%d%d%d",&u,&v,&w);
             while (t[k+1]<=w && k<n-1) 
                   {
                      k++;
                      for (int i=0; i<=n-1; i++)
                           for (int j=0; j<=n-1; j++)
                                f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
                   }
             if (u>k || v>k || f[u][v]==INF) printf("%d\n",-1);
                                        else printf("%d\n",f[u][v]);
        }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值