NYOJ-975 关于521

本文介绍了一道编程题,目标是在指定范围内找出包含5、2、1三个数字的整数,特别关注连续出现521的情况。提供了三种解题思路:普通方法、动态规划和使用C++标准库函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于521

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述

Acm队的流年对数学的研究不是很透彻,但是固执的他还是想一头扎进去。

浏览网页的流年忽然看到了网上有人用玫瑰花瓣拼成了521三个数字,顿时觉得好浪漫,因为每个男生都会不经意的成为浪漫的制造者。此后,流年走到哪里都能看到521三个数字,他怒了,现在他想知道在连续的数中有多少数全部包含了这三个数字。例如12356就算一个,而5111就不算。特别的,如果他看到了521三个数连续出现,会特别的愤怒。例如35210

输入
多组测试数据:
一行给定两个数a,b(0<a,b<1000000),表示数字的开始和结束。
输出
一行显示他想要知道的数有几个及显示有多少个数字令他特别的愤怒。用空格隔开。
样例输入
200 500
300 900
1 600
样例输出
Case 1:2 0
Case 2:2 1
Case 3:6 1


            

3种方法


1.普通方法

01.#include<iostream>
02.using namespace std;
03.#define MAX 1000000
04.int main()
05.{
06.int a,b;
07.int s[6],d1[MAX],d2[MAX];
08.for(int i=125;i<1000000;i++)
09.{
10.int n5=0,n2=0,n1=0;
11.s[0]=i%10;
12.s[1]=i/10%10;
13.s[2]=i/100%10;
14.s[3]=i/1000%10;
15.s[4]=i/10000%10;
16.s[5]=i/100000%10;
17.int t;
18.for(int j=0;j<4;j++)
19.{
20.if(s[j]==1&&s[j+1]==2&&s[j+2]==5)
21.{
22.d2[i]=d2[i-1]+1;
23.break;
24.}
25.if(j==3)
26.d2[i]=d2[i-1];
27.}
28.for(int j=0;j<6;j++)
29.{
30.if(s[j]==5)
31.n5++;
32.else if(s[j]==2)
33.n2++;
34.else if(s[j]==1)
35.n1++;
36.if(n1&&n2&&n5)
37.d1[i]=d1[i-1]+1;
38.else
39.d1[i]=d1[i-1];
40.}
41.}
42.int count=0;
43.while(cin>>a>>b)
44.{
45.count++;
46.if(a<2)
47.a=2;
48.cout<<"Case "<<count<<":"<<d1[b]-d1[a-1]<<" "<<d2[b]-d2[a-1]<<endl;
49.}  
50.return 0;
51.}




2.动态规划

01.#include<stdio.h>
02.int a[2][1000001]={0};
03.int main()
04.{
05.int k=0,i,sum=0;
06.for(i=1;i<=1000000;i++)
07.{
08.if((i%10==5||(i/10)%10==5||(i/100)%10==5||(i/1000)%10==5||(i/10000)%10==5||(i/100000)%10==5)&&(i%10==2||(i/10)%10==2||(i/100)%10==2||(i/1000)%10==2||(i/10000)%10==2||(i/100000)%10==2)&&(i%10==1||(i/10)%10==1||(i/100)%10==1||(i/1000)%10==1||(i/10000)%10==1||(i/100000)%10==1))
09.{
10.sum++;
11.if(i/1000==521||(i/100)%1000==521||(i/10)%1000==521||i%1000==521)
12.k++;
13.}
14.a[0][i]+=sum;
15.a[1][i]+=k;
16.}
17.int m,n,w=0;
18.while(scanf("%d%d",&n,&m)!=EOF)
19.printf("Case %d:%d %d\n",++w,a[0][m]-a[0][n-1],a[1][m]-a[1][n-1]);
20.}




3.c++库函数

01.#include<iostream>
02.#include <string>
03.#include <sstream>
04.#include <cstdio>
05.#include <cstdlib>
06.using namespace std;
07.//用打表法解决,本题将整数转换成字符串,然后查找字符串判断是否有5,2,1,521
08.//题目感觉略坑,直接用stringstrean去将整数转换成字符串超时,但用sprintf可以通过
09.int table[1000000]={0},table521[1000000]={0};
10. 
11.void make_table()
12.{
13.for(int i = 125; i < 1000000; ++ i)
14.{
15.table[i]=table[i-1];
16.table521[i] = table521[i-1];
17.char c[10];
18.sprintf(c,"%d",i);
19./*
20.stringstream ss;
21.ss << i;
22.string num(ss.str());*/
23.string num(c);
24.if(num.find('5')!= string::npos && num.find('2')!=string::npos && num.find('1')!=string::npos){
25.table[i]++;
26.if(num.find("521")!=string::npos) table521[i]++;
27.}
28.}
29.}
30. 
31.int main()
32.{
33.make_table();
34.int a,b,cnt = 0;
35.while(cin >> a >> b){
36.printf("Case %d:%d %d\n",++cnt,table[b]-table[a-1],table521[b] - table521[a-1]);
37.}
38.}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值