我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。要求每位数字都要被旋转。
如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。0, 1, 和 8 被旋转后仍然是它们自己;2 和 5 可以互相旋转成对方;6 和 9 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。
现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?
我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。要求每位数字都要被旋转。
如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。0, 1, 和 8 被旋转后仍然是它们自己;2 和 5 可以互相旋转成对方;6 和 9 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。
现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?
输入正整数N
输出1到N中好数个数
10
4
在[1, 10]中有四个好数: 2, 5, 6, 9。
注意 1 和 10 不是好数, 因为他们在旋转之后不变。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
public class Solution4_X游戏 {
static HashMap<Character, Character> map = new HashMap<>();
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(bf.readLine());
map.put('0', '0');
map.put('1', '1');
map.put('8', '8');
map.put('2', '5');
map.put('5', '2');
map.put('6', '9');
map.put('9', '6');
int count = 0;
for (int i = 1; i <= n; i++) {
if (isGoodNum(i)) count++;
}
System.out.println(count);
}
//自己第一时间写的,相比下面的方法显得有些笨重了...
private static boolean isGoodNum(int x) {
String s = String.valueOf(x);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) {
sb.append(map.get(s.charAt(i)));
} else {
return false;
}
}
return x == Integer.parseInt(sb.toString()) ? false : true;
}
/**
* 此法更优,如果数字是 0 1 8,flag不需要变,它序x值相等
*/
private static boolean isGoodNum1(int x) {
boolean flag = false;
int a = 0;
while (x > 0) {
a = x % 10;
if (a == 3 || a == 4 || a == 7) {
return false;
} else if (a == 2 || a == 5 || a == 6 || a == 9) {
flag = true;
}
x /= 10;
}
return flag;
}
}
n = int(input())
cnt = 0
for i in range(1, n + 1):
numSet = set(list(str(i)))
if ('2' in numSet&nbs***bsp;'5' in numSet&nbs***bsp;'6' in numSet&nbs***bsp;'9' in numSet) and ('3' not in numSet and '4' not in numSet and '7' not in numSet):
cnt += 1
print(cnt) /*
我的想法是将每个数都拆开,看看他里面是不是只包含0,1,2,5,6,8,9,并且旋转之后两个数是否一样
*/
import java.util.Scanner;
public class Main{
//判断是否是好数
public static boolean isGood(int num){
String str = String.valueOf(num);
StringBuffer sb = new StringBuffer();
sb.append(str);//将整数转成字符串
for(int i = 0;i<sb.length();i++){
if(sb.charAt(i)=='0'){
sb.setCharAt(i,'0');
}else if(sb.charAt(i)=='1'){
sb.setCharAt(i,'1');
}else if(sb.charAt(i)=='2'){
sb.setCharAt(i,'5');
}else if(sb.charAt(i)=='5'){
sb.setCharAt(i,'2');
}else if(sb.charAt(i)=='6'){
sb.setCharAt(i,'9');
}else if(sb.charAt(i)=='9'){
sb.setCharAt(i,'6');
}else if(sb.charAt(i)=='8'){
sb.setCharAt(i,'8');
}
else{
return false;
}
}
//判断旋转之后两个数是否一样
int newnum = Integer.parseInt(sb.toString());
if(newnum!=num)return true;
return false;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int N = input.nextInt();
int count = 0;//记录个数
for(int i = 1;i<=N;i++)
if(isGood(i))
count++;
System.out.println(count);
}
} """ 暴力枚举,判断是不是好数 """ def is_good(s): if '3' in s or '4' in s or '7' in s: return False if '2' in s or '5' in s or '6' in s or '9' in s: return True return False if __name__ == "__main__": N = int(input().strip()) ans = 0 for i in range(1, N + 1): if is_good(str(i)): ans += 1 print(ans)
#include <bits/stdc++.h>using namespace std;bool f(string s){int l = s.length();bool change = false;for(int i=0;i<l;i++){if(s[i]=='2' || s[i]=='5' || s[i]=='6' || s[i]=='9'){change = true;continue;}else if(s[i]=='1' || s[i]=='0' || s[i]=='8')continue;elsereturn false;}if(change)return true;elsereturn false;}int main(){long n, cnt=0;cin>>n;for(long i=1;i<=n;i++){string s = to_string(i);if(f(s))cnt++;}cout<<cnt<<endl;return 0;}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,res=0;
cin>>n;
for(int i=1;i<=n;i++)
{
string s=to_string(i);
if((s.find("3")== string::npos&&s.find("4")== string::npos&&s.find("7")== string::npos)&&(s.find("2")!= string::npos||s.find("5")!= string::npos||s.find("6")!= string::npos||s.find("9")!= string::npos))
res++;
}
cout<<res<<endl;
return 0;
}
以下是思路代码,没有通过cases,貌似有地方挂掉了
而且事实上这个代码的效率低于暴力穷举……
但我还是把这个贴出来,因为这个思路的正确写法效率可以很高。
以下是错误代码:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
struct item {
int nums[10];
};
class Solution {
public :
// 入口
int solve(int n) {
// 存每一位的数字
vector<int> mods;
// 统计有多少位
int k = get_k(n, mods);
// 分别对有效数和好数进行dp
vector<item> dp0;
vector<item> dp1;
make_dp(k, dp0, dp1);
int count = 0;
// 当某一位确定强有效时变为真
bool flag = false;
for(int i=k-1; i>=0; i--) {
int m = mods[i];
// 值为1代表强有效,0代表弱有效,-1代表无效
int u = is_useful(m);
// 如果前面有一位已经是强有效了,那么后面弱有效就可以了
if(flag) {
if(u == -1) {
count += dp0[i].nums[m-1];
break;
} else {
count += dp0[i].nums[m-1];
}
} else {
if(u == -1) {
count += dp1[i].nums[m-1];
break;
} else if(u == 0) {
count += dp1[i].nums[m-1];
} else {
count += dp0[i].nums[m-1];
flag = true;
}
}
}
return count;
}
void make_dp(int k, vector<item> &dp0, vector<item> &dp1) {
item item0; int a[] = {1,2,3,3,3,4,5,5,6,7};
item item1; int b[] = {1,2,3,3,3,4,5,5,6,7};
memcpy(item0.nums, a, sizeof(a));
memcpy(item1.nums, b, sizeof(b));
dp0.push_back(item0);
dp1.push_back(item1);
for(int i=1; i<k; i++) {
item marks0;
item marks1;
marks0.nums[0] = pow(7,i);
marks1.nums[0] = dp1.back().nums[9];
for(int m=1; m<10; m++) {
int u = is_useful(m);
if(u==-1) {
marks0.nums[m] = marks0.nums[m-1];
marks1.nums[m] = marks1.nums[m-1];
} else if(u==0) {
marks0.nums[m] = marks0.nums[m-1] + marks0.nums[0];
marks1.nums[m] = marks1.nums[m-1] + marks1.nums[0];
} else {
marks0.nums[m] = marks0.nums[m-1] + marks0.nums[0];
marks1.nums[m] = marks1.nums[m-1] + marks0.nums[0];
}
}
dp0.push_back(marks0);
dp1.push_back(marks1);
}
}
int is_useful(int m) {
if(m==3||m==4||m==7) return -1;
if(m==0||m==1||m==8) return 0;
return 1;
}
int get_k(int n, vector<int> mods) {
int k=0;
while(n!=0) {
mods.push_back(n % 10);
k++;
n/=10;
}
return k;
}
int pow(int x, int p) {
int r = 1;
while(p-->0) {
r*=x;
}
return r;
}
};
int main(void) {
int n;
scanf("%d", &n);
int result = Solution().solve(n);
printf("%d", result);
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int count = 0;
for (int i = 1; i <= n; i++) {
String str = String.valueOf(i);
// 包含2、5、6、9中任意个,且不包含3、4、7的即为好数
if ((str.contains("2") || str.contains("5") || str.contains("6") || str.contains("9")) && (!str.contains("3") && !str.contains("4") && !str.contains("7"))) {
count++;
}
}
System.out.println(count);
}
}
#include <iostream>
using namespace std;
int main()
{
int num = 0;
cin>>num;
int counter = 0;
string other = "2569";
string bad = "347";
for(int i=2;i<=num;i++)
{
string str = to_string(i);
if(str.find_first_of(bad) == str.npos && str.find_first_of(other) != str.npos)
counter++;
}
cout<<counter<<endl;
return 0;
}
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int main()
{
int N, count = 0;
int flag[10] {1,1,2,0,0,2,2,0,1,2};//这个数的性质,不可翻,翻转相同,翻转不同
int T[10] {1,2,3,3,3,4,5,5,6,7};//这个数字之前有多少个可翻转
int F[10] {1,2,2,2,2,2,2,2,3,3};//之前有多少个翻转相同
vector<int> n;
cin>>N;
while(N!=0)
{
n.push_back(N%10);
N /= 10;
}
count += T[n[n.size()-1]-1] * pow(7, n.size()-1) - F[n[n.size()-1]-1] * pow(3,n.size()-1);
bool f = false;
if(flag[n[n.size()-1]] == 2) f = true; //存在翻转不同
int i;
for(i = n.size()-2; i >= 0; i--)
{
if(n[i]==0) continue;
if(flag[n[i+1]] == 0) break;
count += T[n[i]-1] * pow(7, i);
if(!f) count -= F[n[i]-1] * pow(3, i);//不存在翻转不同
if(flag[n[i]] == 2) f = true;//出现了翻转不同的数字
}
if(flag[n[i+1]] != 0 && n[i] == 0 && f) count++;//最后一位是0且最大数是好数
cout<<count;
} import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count = 0;
for (int i = 1; i <= n; i++) {
boolean is_goodNum = false;
boolean is_badNum = false;
int mod = i;
while (mod > 0) {
int yu = mod % 10;
if (yu == 2 || yu == 5 || yu == 6 || yu == 9) {
is_goodNum = true;
}
if (yu == 3 || yu == 4 || yu == 7) {
is_badNum = true;
}
mod /= 10;
}
if (is_goodNum == true && is_badNum == false) {
count++;
}
}
sc.close();
System.out.println(count);
}
} #include<bits/stdc++.h>
using namespace std;
inline bool check(int x)
{
int flag=0;
while(x)
{
int q=x%10;
x/=10;
if(q==2||q==5||q==6||q==9) flag=1;
else if(q==0||q==1||q==8) continue;
else return false;
}
if(flag) return true;
else return false;
}
int main()
{
int n,sum=0;cin>>n;
for(int i=1;i<=n;i++)
if(check(i)) sum++;
cout<<sum;
} #include<iostream>
using namespace std;
int main(){
int n,count=0;
int a,b,m;
bool effecient=false;
cin>>n;
m=n;
while(m)
{
effecient=false;
while(n)
{
a=n/10;
b=n-a*10;
if(b==2||b==5||b==6||b==9)
{
effecient=true;
}
if(b==3||b==7||b==4)
{
effecient=false;
break;
}
n=n/10;
}
if(effecient)
count++;
m--;
n=m;
}
cout<<count;
return 0;
}
要判断每位数,一个数字包括了3、4、7都是无效数字,退出循环,包括了2、5、6、9属于有效数字,可以进行累加,
先求出所有由0, 1, 2, 5, 6, 8, 9构成的且小于N的数的个数res,这些数是翻转有效的,然后求出所有由0, 1, 8构成的且小于N的数的个数las,这些数是翻转有效而且翻转后等于自己。res-las就是所求的答案。
#include <iostream>
#include <vector>
using namespace std;
int power7(int x)
{
int res = 1;
for (int i = 0; i < x; i ++) res *= 7;
return res;
}
int power3(int x)
{
int res = 1;
for (int i = 0; i < x; i ++) res *= 3;
return res;
}
int main()
{
int f[7] = {0, 1, 2, 5, 6, 8, 9};
int g[3] = {0, 1, 8};
int n;
cin >> n;
vector<int> vec;
while (n)
{
vec.push_back(n % 10);
n /= 10;
}
int res = 0;
int las = 0;
for (int i = vec.size() - 1; i >=0; i --)
{
for (int j = 0; j < 7; j ++)
{
int x = f[j];
if (x < vec[i]) res += power7(i);
}
if (vec[i] == 3 || vec[i] == 4 || vec[i] == 7) break;
if (!i) res ++;
}
for (int i = vec.size() - 1; i >= 0; i --)
{
for (int j = 0; j < 3; j ++)
{
int x = g[j];
if (x < vec[i]) las += power3(i);
}
if (!(vec[i] == 0 || vec[i] == 1 || vec[i] == 8)) break;
if (!i) las ++;
}
cout << res - las << endl;
return 0;
}