UESTC 1808 琪露诺的算术教室 打表+特判(找规律)

题目

琪露诺是个聪明的精灵,她非常擅长和数字有关的游戏 .
直到有一天灵梦进入了迷雾深林,她遇见了琪露诺,并向她提出了一个问题.
统计n个一位数字a组成的数乘以一位数b的结果中有多少个一位数字d.不超过100000组数据.

解析

本来是找规律的题强行被我做成了打表题.
首先找出你的高精度模板,枚举a和b,令n=10,将结果输出如下:(d=0)

81
1 1 0 10
1 2 0 10
1 3 0 10
1 4 0 10
1 5 0 10
1 6 0 10
1 7 0 10
1 8 0 10
1 9 0 10
2 1 0 10
2 2 0 10
2 3 0 10
2 4 0 10
2 5 0 10
2 6 0 10
2 7 0 10
2 8 0 10
2 9 0 10
3 1 0 10
3 2 0 10
3 3 0 10
3 4 0 10
3 5 0 10
3 6 0 10
3 7 0 10
3 8 0 10
3 9 0 10
4 1 0 10
4 2 0 10
4 3 0 10
4 4 0 10
4 5 0 10
4 6 0 10
4 7 0 10
4 8 0 10
4 9 0 10
5 1 0 10
5 2 0 10
5 3 0 10
5 4 0 10
5 5 0 10
5 6 0 10
5 7 0 10
5 8 0 10
5 9 0 10
6 1 0 10
6 2 0 10
6 3 0 10
6 4 0 10
6 5 0 10
6 6 0 10
6 7 0 10
6 8 0 10
6 9 0 10
7 1 0 10
7 2 0 10
7 3 0 10
7 4 0 10
7 5 0 10
7 6 0 10
7 7 0 10
7 8 0 10
7 9 0 10
8 1 0 10
8 2 0 10
8 3 0 10
8 4 0 10
8 5 0 10
8 6 0 10
8 7 0 10
8 8 0 10
8 9 0 10
9 1 0 10
9 2 0 10
9 3 0 10
9 4 0 10
9 5 0 10
9 6 0 10
9 7 0 10
9 8 0 10
9 9 0 10
1111111111
2222222222
3333333333
4444444444
5555555555
6666666666
7777777777
8888888888
9999999999
2222222222
4444444444
6666666666
8888888888
11111111110
13333333332
15555555554
17777777776
19999999998
3333333333
6666666666
9999999999
13333333332
16666666665
19999999998
23333333331
26666666664
29999999997
4444444444
8888888888
13333333332
17777777776
22222222220
26666666664
31111111108
35555555552
39999999996
5555555555
11111111110
16666666665
22222222220
27777777775
33333333330
38888888885
44444444440
49999999995
6666666666
13333333332
19999999998
26666666664
33333333330
39999999996
46666666662
53333333328
59999999994
7777777777
15555555554
23333333331
31111111108
38888888885
46666666662
54444444439
62222222216
69999999993
8888888888
17777777776
26666666664
35555555552
44444444440
53333333328
62222222216
71111111104
79999999992
9999999999
19999999998
29999999997
39999999996
49999999995
59999999994
69999999993
79999999992
89999999991

然后发现中间的数字肯定是同一个,对这个数字打表.(9*9的表)

int i,j,biao[10][10]={{0,0,0,0,0,0,0,0,0,0},//When n is large,the number which will repeat in the result
                      {0,1,2,3,4,5,6,7,8,9},
                      {0,2,4,6,8,1,3,5,7,9},
                      {0,3,6,9,3,6,9,3,6,9},
                      {0,4,8,3,7,2,6,1,5,9},
                      {0,5,1,6,2,7,3,8,4,9},
                      {0,6,3,9,6,3,9,6,3,9},        
                      {0,7,5,3,1,8,6,4,2,9},
                      {0,8,7,6,5,4,3,2,1,9},
                      {0,9,9,9,9,9,9,9,9,9}};

可以发现一般来说中间的数字都是n-1个,那么我们把去掉n-1个数字剩下的数字再打第二个表.

int biao2[10][10]={{0,0,0,0,0,0,0,0,0,0},//When n is large,the number that will remain after removing n-1(n-2) digits of biao[a][b]
                   {0,1,2,3,4,5,6,7,8,9},
                   {0,2,4,6,8,10,12,14,16,18},
                   {0,3,6,9,12,15,18,21,24,27},
                   {0,4,8,12,16,20,24,308,32,36},
                   {0,5,10,15,20,25,30,35,40,45},
                   {0,6,12,18,24,30,36,42,528,54},
                   {0,7,14,21,308,35,42,539,616,63},
                   {0,8,16,24,32,40,528,616,704,72},
                   {0,9,18,27,36,45,54,63,72,81}};

可以看到有一些情况不符合常规,多出来三位数字.我们用几个pair来标记一下.

pii tepan[5]={mp(4,7),mp(6,8),mp(7,7),mp(7,8),mp(8,8)};

然而还没完.当n=1时没有这样的情况,所以要单独拿出来.故AC代码如下.

#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
using namespace std;
int t,n,a,b,d;
int main()
{
int i,j,biao[10][10]={{0,0,0,0,0,0,0,0,0,0},//When n is large,the number which while repeat in the result
                      {0,1,2,3,4,5,6,7,8,9},
                      {0,2,4,6,8,1,3,5,7,9},
                      {0,3,6,9,3,6,9,3,6,9},
                      {0,4,8,3,7,2,6,1,5,9},
                      {0,5,1,6,2,7,3,8,4,9},
                      {0,6,3,9,6,3,9,6,3,9},              
                      {0,7,5,3,1,8,6,4,2,9},
                      {0,8,7,6,5,4,3,2,1,9},
                      {0,9,9,9,9,9,9,9,9,9}};
int biao2[10][10]={{0,0,0,0,0,0,0,0,0,0},//When n is large,the number that while remain after removing n-1(n-2) digits of biao[a][b]
                   {0,1,2,3,4,5,6,7,8,9},
                   {0,2,4,6,8,10,12,14,16,18},
                   {0,3,6,9,12,15,18,21,24,27},
                   {0,4,8,12,16,20,24,308,32,36},
                   {0,5,10,15,20,25,30,35,40,45},
                   {0,6,12,18,24,30,36,42,528,54},
                   {0,7,14,21,308,35,42,539,616,63},
                   {0,8,16,24,32,40,528,616,704,72},
                   {0,9,18,27,36,45,54,63,72,81}};
pii tepan[5]={mp(4,7),mp(6,8),mp(7,7),mp(7,8),mp(8,8)};
for (scanf("%d",&t);t--;)
  {
  int ans=0,tong[10]={0};
  scanf("%d%d%d%d",&a,&b,&d,&n);
  if (a>b) swap(a,b);//从两个表当中可以看出a,b是可以交换的
  if (n==1)//直接计算
    {
    int t=a*b;
    for (;t;t/=10) tong[t%10]++;
    ans+=tong[d];
    }
  else 
    {
    if (biao[a][b]==d)  
      {
      ans=n-1;//一般情况都是n-1个
      pii t=*lower_bound(tepan,tepan+5,mp(a,b));//看看是不是在特判的五种情况之中
      if (a==t.first&&b==t.second) ans--;//如果是再减一个
      }
    int t=biao2[a][b];//枚举剩下的
    for (;t;t/=10) tong[t%10]++;
    ans+=tong[d];
    }
  printf("%d\n",ans);
  }
}

琪露诺实在太强了,算术教室都要打表才能过.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值