【链接】:https://www.luogu.org/problemnew/show/P1618

题目描述

将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”。

//感谢黄小U饮品完善题意

输入输出格式

输入格式:

三个数,A B C。

输出格式:

若干行,每行3个数字。按照每行第一个数字升序排列。

输入输出样例

输入样例#1:
复制

1 2 3
输出样例#1: 复制

192 384 576
219 438 657
273 546 819
327 654 981

说明

保证A<B<C

【分析】:

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int a,b,c,num,i1,i2,i3,flag=;
cin>>i1>>i2>>i3;
for(num=;num<=;num++){
a=i1*num;b=i2*num;c=i3*num;
if((a/+a/%+a%+b/+b/%+b%+c/+c/%+c%==)&&((a/)*(a/%)*(a%)*(b/)*(b/%)*(b%)*(c/)*(c/%)*(c%)==)){
cout<<a<<" "<<b<<" "<<c<<endl;
flag=;
}
}
if(flag==){
cout<<"No!!!";
}
return ; }

普通枚举

1.

枚举每一个可能的数,将三个倍数保存在数组中,再排序,最后通过和标准的“123456789”比较,如果相同,则满足条件。这样用一个常量数组,可以简化计算,不需要过多的思考。所以说常量数组大法真的好~因为之前做过三连击的简单版,就有了思维定式,枚举总是从123开始,所以最后一个(数据是123 456 789)总是错。最后一个过不去的同学可以试试从1开始枚举,就会过去了。

#include <bits/stdc++.h>

using namespace std;

char stdanard[]="";

int a,b,c;

int main()
{
int flag=;
cin>>a>>b>>c;
for(int i=;i<=;i++)
{
char buf[];//开大防止溢出
sprintf(buf,"%d%d%d",a*i,b*i,c*i);
sort(buf,buf+);
if(strcmp(stdanard,buf)==)
{
flag=;
printf("%d %d %d\n",a*i,b*i,c*i);
}
}
if(flag) puts("No!!!");
return ;
}

sprintf

2.我和大部分人思路基本一样,不一样的地方在于对三个数组成的9个数的拆分上,我用的是sstream头文件,将三个数放到一个字符串中去,这样就不用%或者/去费力拆分了,写起来更优雅,然后将字符串每个数加起来 乘起来,即可验证是否为不同的9个数。

/*
对三个数组成的9个数的拆分上,用的是sstream头文件,
将三个数放到一个字符串中去,
这样就不用%或者/去费力拆分了,写起来更优雅,
然后将字符串每个数加起来 乘起来,即可验证是否为不同的9个数。
*/
#include <bits/stdc++.h> using namespace std; stringstream ss;
string str;
int cnt=;
int a,b,c; int main()
{
cin>>a>>b>>c; for(int i=;i<=;i++)
{
int j=i*b/a;
int k=i*c/a;
int sum=;
int pro=;
ss<<i<<j<<k;
ss>>str;
ss.clear(); for(int j=;j<;j++)
{
sum+=str[j]-'';
pro*=str[j]-'';
} if(sum== && pro==)
{
cout<<i<<" "<<j<<" "<<k<<" "<<endl;
cnt++;
} }
if(!cnt) puts("No!!!");
return ;
}

stringstream

3.

/*
其实判断是否相等不需要if(a==b&&b==c...)这样乱七八糟的打一大坨,一个数组就能完成。如下:
*/
#include <bits/stdc++.h> using namespace std; int d[];//数组d判断位数是否相等。
int main()
{
float x,y,z;
int a,b,c,t=,j=;//j判断是否有解
cin>>x>>y>>z;//即A、B、C
for(a=;a<=;a++)//枚举最小的那个数
{
b=y*a/x;
c=z*a/x;
d[a/]++;
d[(a%)/]++;
d[a%]++; d[b/]++;
d[(b%)/]++;
d[b%]++; d[c/]++;
d[(c%)/]++;
d[c%]++;
for(int bb=;bb<=;bb++)
{
if(d[bb]==) t=;//由于总共只有九个数字,若有一个数没有出现,就说明有数字重复了。
d[bb]=;//归零
}
if(t==) {cout<<a<<" "<<b<<" "<<c<<endl;j=;}//若有解,输出a、b、c
t=;
}
if(!j) cout<<"No!!!";
return ;
}

数组技巧性枚举

# include <stdio.h>
# define MUL(x) (x%)*(x/%)*(x/) //一个三位数x所包含的3个数的乘积为MUL(x)
# define ADD(x) (x%)+(x/%)+(x/) //一个三位数x所包含的3个数的总和为ADD(x)
const product=********; //数字1—9的乘积为product
const int sum=++++++++; //数字1—9的总和为sum
int main()
{
int A,B,C,a=,Yes=; //变量Yes用于检测是否有解
scanf("%d %d %d",&A,&B,&C); //输入3个三位数的比例A:B:C(A<B<C且为最简比)
while(++a*A<); //保证这3个数中最小的数是三位数
for(;a*C<;a++) //保证这3个数中最大的数是三位数
if(product==MUL(a*A)*MUL(a*B)*MUL(a*C) //倘若它们所包含的9个数的乘积恰好为product
&& sum==ADD(a*A)+ADD(a*B)+ADD(a*C)) //并且总和恰好为sum时,说明没有重复数字和0
Yes=printf("%i %i %i\n",a*A,a*B,a*C); //输出这3个由1—9组成的三位数,并给Yes赋值
if(!Yes) //若无解
puts("No!!!"); //则输出“No!!!”
return ;
}

技巧性枚举

4.

#include<iostream>
using namespace std;
int x[]={},a,b,c; //x[1]~x[9]为当前位置的数字 先把三个三位数合成一个9(10)位数的大数组
bool used[]={},ans=false;
//used数组表示该数字的使用情况 避免重复 ans判断是否有答案
int cons(int m){ //将数组拆分成三个三位数
int sum=;
for(int i=*m-;i<=*m;i++){
sum*=;
sum+=x[i];
}
return sum;
}
void solve(int n){
if(n==&&cons()*b==cons()*a&&cons()*c==cons()*a){ //当n=10时x数组数字存满 开始判断
cout<<cons()<<" "<<cons()<<" "<<cons()<<endl;
ans=true;
return;
}
for(int i=;i<=;i++){
if(!used[i]){
x[n]=i; //存数字
used[i]=; //该数字被使用
solve(n+); //下一位继续调用
used[i]=; //恢复
}
}
return;
}
int main(){
cin>>a>>b>>c;
solve(); //开始搜索
if(!ans) cout<<"No!!!"; //ans!=true即输出"No!!!"
return ;
}

DFS

5.STL中的next_permutation函数提供下一个排列功能,是用生成法实现的,所以速度要比搜索快多了。

#include<bits/stdc++.h>
using namespace std;
int a[]={,,,,,,,,,};
int main()
{
int A,B,C,h=;
cin>>A>>B>>C;
int t=A*B*C;
A=t/A;
B=t/B;
C=t/C;
do{
if((*a[]+*a[]+a[])*A==(*a[]+*a[]+a[])*B&&(*a[]+*a[]+a[])*A==(*a[]+*a[]+a[])*C)//如果符合比例;
{
cout<<a[]<<a[]<<a[]<<" "<<a[]<<a[]<<a[]<<" "<<a[]<<a[]<<a[]<<endl;//输出
h++;
}
}while(next_permutation(a+,a+));//STL中的下一个排列函数;
if(h==) cout<<"No!!!";//没有解输出NO;
return ;
}

next_permutation()

#include<iostream>
#include<algorithm>
using namespace std;
int a[] = { , , , , , , , , };
bool isSame(int v[], int a[]) {
for (int i = ; i != ; i++)
if (v[i] != a[i])
return false;
return true;
}
int main()
{
int A, B, C;
int visit[] = { };
int pos;
bool flag = false;
cin >> A >> B >> C;
do {
int x = a[] * + a[] * + a[];
int y = a[] * + a[] * + a[];
int z = a[] * + a[] * + a[];
int a[] = { x, y, z };
sort(a, a + );
if (!isSame(visit, a)) {
if ((double)y / x == (double)B / A && (double)z / x == (double)C / A && (double)z / y == (double)C / B) {
cout << a[] << " " << a[] << " " << a[] << endl;
flag = true;
}
}
} while (next_permutation(a, a + ));
if (flag == false)
cout << "No!!!" << endl;
return ;
}

5.2

洛谷 P1618 三连击(升级版)【DFS/next_permutation()/技巧性枚举/sprintf】的更多相关文章

  1. 洛谷——P1618 三连击(升级版)

    P1618 三连击(升级版) 题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”. //感谢 ...

  2. (水题)洛谷 - P1618 - 三连击(升级版)

    https://www.luogu.org/problemnew/show/P1618 枚举所有的A,最多 $A_9^3$ ,然后生成B和C(先判断是不是能够生成),判断有没有重复数字(比之前那个优雅 ...

  3. 洛谷 P1618 三连击(升级版)

    题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”. //感谢黄小U饮品完善题意 输入输出格 ...

  4. Java实现 洛谷 P1618 三连击(升级版)

    import java.util.Arrays; import java.util.Scanner; public class Main { private static Scanner cin; p ...

  5. 洛谷 p1008三连击

    洛谷 p1008三连击 题目背景 本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序. 题目描述 将1,2, ⋯,9共99个数分成3组,分别组成3个三位数, ...

  6. 【题解】洛谷P3166 [CQOI2014] 数三角形(组合+枚举)

    洛谷P3166:https://www.luogu.org/problemnew/show/P3166 思路 用组合数求出所有的3个点组合(包含不合法的) 把横竖的3个点共线的去掉 把斜的3个点共线的 ...

  7. 题解【洛谷P1618】 三连击(升级版)

    设三个数分别为n1.n2.n3,因为三个数的比为A:B:C,取一份量i,使得A·i=x,B·i=y,C·i=z(·是*的意思). 所以我们的代码只需要枚举i,并以此判断n1.n2.n3是否为三位数且包 ...

  8. 洛谷P1120小木棍[DFS]

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...

  9. 洛谷P1605 迷宫 (DFS)

    题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和 终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫 中移动有上下 ...

随机推荐

  1. 3 View - 状态保持 session

    1.状态保持 http协议是无状态的:每次请求都是一次新的请求,不会记得之前通信的状态 客户端与服务器端的一次通信,就是一次会话 实现状态保持的方式:在客户端或服务器端存储与会话有关的数据 存储方式包 ...

  2. “帮你APP”团队冲刺7

    1.整个项目预期的任务量 (任务量 = 所有工作的预期时间)和 目前已经花的时间 (所有记录的 ‘已经花费的时间’),还剩余的时间(所有工作的 ‘剩余时间’) : 所有工作的预期时间:88h 目前已经 ...

  3. github readme.md 添加图片

    简要: 将图片放在仓库里面,在文件里链接它,最后 push 到 github 上. github 图片链接格式: (http://github.com/yourname/your-repository ...

  4. Monkey log异常分析说明

    以下主要针对在Android-Phone项目中进行Monkey log进行分析和说明,可以对bug提交作为参考. 要求熟悉,应用的包名.也就是说那个应用包出现问题,该属于那个模块,应用包名是判断依据. ...

  5. Android 使用剪贴板传递简单数据及复杂数据的方法

    传递数据的场景在于不同页面之间跳转,需要携带数据:简单数据值指的是String, int等数据, 复杂数据指的是类 1.   使用剪贴板传递简单数据方法: 第一个页面里面放数据操作如下: Clipbo ...

  6. live 555 freebsd 或centos 7.4 实现代理视频直播服务

    live 555   freebsd 或centos 7.4 实现代理视频直播服务 the live555 media server    在线直播服务器 关于此服务器 此服务是一个无安全的rtsp服 ...

  7. Pipenv 学习笔记

    个人笔记,胡言乱语.并不是什么教学向文章.. 前言 在学习了 Python.Java 后,会发现 Java 有很成熟的项目构建工具,以前是使用 xml 的 Maven,现在又出现了使用 groovy ...

  8. linux常用命令(复制)

    显示目录和文件的命令    Ls:用于查看所有文件夹的命令. Dir:用于显示指定文件夹和目录的命令   Tree: 以树状图列出目录内容 Du:显示目录或文件大小 修改目录,文件权限和属主及数组命令 ...

  9. (转)对称加密与非对称加密,以及RSA的原理

    一 概述 二对称加密和非对称加密 对称加密 非对称加密 区别 三RSA原理 整数运算 同余运算 当模数为合数n时 当模数为质数p的时候 离散对数问题 RSA原理 一 , 概述 在现代密码学诞生以前,就 ...

  10. Socket通信入门小实例

    客户端: public class Client { private int port = 8000; private String host = "localhost"; pri ...