题目描述 这一天,TT因为疫情在家憋得难受,在云吸猫一小时后,TT决定去附近自家的山头游玩。
TT来到一个小湖边,看到了许多在湖边嬉戏的鸭子,TT顿生羡慕。此时他发现每一只鸭子都不 一样,或羽毛不同,或性格不同。TT在脑子里开了一个map<鸭子,整数> tong,把鸭子变成了 一些数字。现在他好奇,有多少只鸭子映射成的数的数位中不同的数字个数小于k。 输入描述 输入第一行包含两个数n,k,表示鸭子的个数和题目要求的k。
接下来一行有n个数,
a
i
a_i
ai,每个数表示鸭子被TT映射之后的值。 输出描述 输出一行,一个数,表示满足题目描述的鸭子的个数。
无行末空格 样例输入
6 5 123456789 9876543210 233 666 1 114514
样例输出
4
数据组成 数据点 n k
a
i
a_i
ai 1 n<=1000 k=10
1
0
6
10^6
106 2 n<=1000 k=1
1
0
6
10^6
106 3,4,5 n<=
1
0
5
10^5
105 k<=100
1
0
9
10^9
109 6,7,8,9,10 n<=
1
0
6
10^6
106 k<=
1
0
6
10^6
106
1
0
15
10^{15}
1015
题目分析:
本题有一个虚晃一枪,就是不同的数字一定是小于等于10个的,所以K大于10那就意味着所有可能出现的数都是符合要求的。但是我们发现输入的数范围太大了,而我们想要的是数位而不是整数,所以我们用字符表示。
char a[20];
然后我们为了统计不重复出现的字符数,我们可以用一个布尔数组来储存,只要出现了就置为true,如果是true就不算了,否则就不同的数字++,之后比较k就可以了。
for(int i=1;i<=n;i++)
{
scanf("%s",&a);
for(int j=0;a[j]!='\0';j++)
{
if(b[a[j]-48]==false)
{
b[a[j]-48]=true;
count++;
}
}
if(count<k)
{
num++;
}
在这里我们发现一个问题,就是在自建的OJ上没问题,但是在VJ上就会TLE,助教解释如下:
关于T1有些同学超时的问题:(我猜你用了STL
正解的复杂度是 151e6,用了stl的话会变成 151e6*log10
你可能认为这个时间复杂度并没有超过 1e8所以不会T
但是你要考虑到 你的程序是有带着一个常数的 而计算复杂度的时候是没有常数的 这个常数是超时的原因
以后做题的时候如果估算时间复杂度发现在1e7左右的时候需要观察题目给出的时限,如果是1s的话就需要注意常数问题
而且评测机的性能是有波动的,有的快有的慢,所以当时间复杂度逼近1e8的时候一定要谨慎。
好的,于是我就照做了,本来我想着是memset的问题,于是我就用手动清零了。
for(int m=0;m<10;m++)
{
b[m]=false;
}
但是当我尝试了1145141919810893364次依然发现在test5上TLE,后来我再品味这句话,加上之前助教给的经验,我突然想到,哦,会不会是要把cin改成scanf?果然啊!以往的时候都直接说了,看来这次也是这个样子!不过改的时候发现问题了,我一开始用的是string啊!好像scanf不能直接用这个,那咋办嘛?!于是改成了char,发现用单个字符是不能直接编译的,于是设了个字符数组,这样就能用scanf输入,之后AC了!!!!!!!看来学长为了让我们用scanf和printf花了不少心思啊(虽然他说一开始没想到卡这个)!
代码如下:
#include<iostream>
using namespace std;
char a[20];
bool b[100];
int main()
{
int n,k;
cin>>n>>k;
int count=0;
int num=0;
for(int i=1;i<=n;i++)
{
scanf("%s",&a);
for(int m=0;m<10;m++)
{
b[m]=false;
}
for(int j=0;a[j]!='\0';j++)
{
if(b[a[j]-48]==false)
{
b[a[j]-48]=true;
count++;
}
}
if(count<k)
{
num++;
}
count=0;
}
cout<<num;
}