目录
一,题目
二,题意分析
三,做法
1.直接模拟题意
2,用筛法来解
3,正解(加上记忆化)
一,题目
二,题意分析
题目意思是说:每次输入一个数,然后先判断这个数是否为某一个十进制中包含7的数的倍数,如果是则输出-1,否则找到该数后的第一个不为任何一个十进制中包含7的数的倍数的数,输出即可。
三,做法
1.直接模拟题意
首先我们程序中必须用一个函数p计算出x的十进制是否中包含7(包含就返回0,否则返回1)
bool p(int x)
{
while(x)
{
if(x % 10 == 7) return 0;
x /= 10;
}
return 1;
}
然后还要一个函数f计算出x是否为某一个十进制中包含7的数的倍数(是就返回0,否则返回1)
bool f(int x)
{
for(int i = 1; i <= x / i; i++)
if(x % i == 0 && (p(i) == 0 || p(x / i) == 0))
//其实也就是枚举x的约数,看看约数中有没有十进制中包含7的数
return 0;
return 1;
}
然后就是主函数。每次输入x,然后判断f(x)是否等于0(判断对方报的数报对了没),是则输出-1(对方没报对),否则从x + 1开始枚举i(枚举你的要报的数),每次都要判断f(i)是否等于1(判断i是否可以报出来),等于1则输出i(可以报),break,否则i继续++
signed main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
if(f(x) == 0) printf("-1\n");
else
{
int i = x + 1;
while(1)
{
if(f(i) == 1)
{
printf("%lld\n",i);
break;
}
i++;
}
}
}
return 0;
}
总体程序:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t,x,l[10000001];
bool p(int x)
{
while(x)
{
if(x % 10 == 7) return 0;
x /= 10;
}
return 1;
}
bool f(int x)
{
for(int i = 1; i <= x / i; i++)
if(x % i == 0 && (p(i) == 0 || p(x / i) == 0))
return 0;
return 1;
}
signed main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
if(f(x) == 0) printf("-1\n");
else
{
int i = x + 1;
while(1)
{
if(f(i) == 1)
{
printf("%lld\n",i);
break;
}
i++;
}
}
}
return 0;
}
2,用筛法来解
我们可以发现,这道题和埃氏筛法的思想很像,其实就是模拟,我们可以用一个vis数组来记录一个数是否应该被跳过。
初始化vis的代码:
void fin()
{
for(int i = 1; i < 10000001; i++)
if(vis[i] == 0 && p(i) == 1)
for(int j = 1; i * j < 10000011; j++)
vis[i * j] = 1;
}
这样我们就预处理好了10^7以内的数是否应该被跳过
于是乎,我又交了一发这样的代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t,x,vis[10000011];
bool p(int x)
{
while(x)
{
if(x % 10 == 7) return 1;
x /= 10;
}
return 0;
}
void fin()
{
for(int i = 1; i < 10000001; i++)
if(vis[i] == 0 && p(i) == 1)
for(int j = 1; i * j < 10000011; j++)
vis[i * j] = 1;
}
signed main()
{
fin();
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
if(x < 0)
{
printf("1");
continue;
}
if(vis[x] == 1) printf("-1\n");
else
{
for(int i = x + 1;i;i++)
{
if(vis[i] == 0)
{
printf("%lld\n",i);
break;
}
}
}
}
return 0;
}
你以为这样就结束了吗?
非也,非也。
我又荣幸地拿到了70分,T了三个点。
3,正解(加上记忆化)
我看了看样例,突然发现样例中多次询问了同一个数,就用l数组来记录已经询问过的数,并在每次询问时都判断一下l[x]是否为0,不为0则直接输出l[x],否则进行计算,最后再把结果记录到l[x]中。
没想到真的AC了。。。
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t,x,l[10000011],vis[10000011];
bool p(int x)
{
while(x)
{
if(x % 10 == 7) return 1;
x /= 10;
}
return 0;
}
void fin()
{
for(int i = 1; i < 10000001; i++)
if(vis[i] == 0 && p(i) == 1)
for(int j = 1; i * j < 10000011; j++)
vis[i * j] = 1;
}
signed main()
{
fin();
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
if(x < 0)
{
printf("1");
continue;
}
if(l[x] != 0)
{
printf("%lld\n",l[x]);
continue;
}
if(vis[x] == 1) printf("-1\n");
else
{
for(int i = x + 1;i;i++)
{
if(vis[i] == 0)
{
l[x] = i;
printf("%lld\n",i);
break;
}
}
}
}
return 0;
}