由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
比如:
210 x 6 = 1260
8 x 473 = 3784
27 x 81 = 2187
都符合要求。
如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。
暴力枚举,四重循环, abcd的值分别从0到9开始 ,然后判断abcd不能相等,然后在不相等的条件下进行乘法运算。乘法运算分为两种情况
a * bcd 和 ab * cd
abcd分别从0-9开始遍历,第一种情况不会出现重复,但第二种情况可能会出现重复,一开始觉得重复会发生在ab大于50 的情况,结果发现 35 和41 也会重复,所以就直接全部遍历再除2解决。
判断结果是否和原来的数字组成相同用的最直观的思路,先两个数字都排序,然后依次遍历是否相等,反正就4位。。相同则++计数。
一开始想两种循环嵌套一起,但是分不清ab cd交换律相同的情况,就将两种情况分别讨论。
12
#include
#include
using namespace std;
int main() {
int a,b,c,d,answer,count=0 , count1 = 0 ;
int org[4];
int ans[4];
for(a = 0; a<10 ; a++){
for(b = 0 ; b < 10; b++){
for(c = 0 ; c < 10 ; c++){
for (d = 0 ; d < 10 ; d++){
if(a!= b && a!=c && a!=d && b!=c && b!=d && c!=d){
org[0] = a; org[1] = b ; org[2] = c; org[3] = d;
sort(org,org+4);
answer = a *(b*100+c*10+d);
if(answer >1000 && answer < 9999){
ans[0] = answer%10; answer = answer/10;
ans[1] = answer%10; answer = answer/10;
ans[2] = answer%10; answer = answer/10;
ans[3] = answer%10;
sort(ans,ans+4);
for (int i = 0; i < 4; ++i) {
if (ans[i] != org[i]){
break;
}
if(i == 3){
count++;
}
}
}
}
}
}
}
}
for(a = 0; a<10 ; a++){
for(b = 0 ; b < 10; b++){
for(c = 0 ; c < 10 ; c++){
for (d = 0 ; d < 10 ; d++){
if(a!= b && a!=c && a!=d && b!=c && b!=d && c!=d){
org[0] = a; org[1] = b ; org[2] = c; org[3] = d;
sort(org,org+4);
answer = (a*10+b)*(c*10+d);
if(answer >1000 && answer < 9999){
ans[0] = answer%10; answer = answer/10;
ans[1] = answer%10; answer = answer/10;
ans[2] = answer%10; answer = answer/10;
ans[3] = answer%10;
sort(ans,ans+4);
for (int i = 0; i < 4; ++i) {
if (ans[i] != org[i]){
break;
}
if(i == 3) {
count1++;
}
}
}
}
}
}
}
}
cout<< count+(count1/2);
}
小李的店里专卖其它店中下架的样品电视机,可称为:样品电视专卖店。
其标价都是4位数字(即千元不等)。
小李为了标价清晰、方便,使用了预制的类似数码管的标价签,只要用颜色笔涂数字就可以了。
这种价牌有个特点,对一些数字,倒过来看也是合理的数字。如:1 2 5 68 9 0 都可以。这样一来,如果牌子挂倒了,有可能完全变成了另一个价格,比如:1958 倒着挂就是:8561,差了几千元啊!!
当然,多数情况不能倒读,比如,1110 就不能倒过来,因为0不能作为开始数字。
有一天,悲剧终于发生了。某个店员不小心把店里的某两个价格牌给挂倒了。并且这两个价格牌的电视机都卖出去了!
庆幸的是价格出入不大,其中一个价牌赔了2百多,另一个价牌却赚了8百多,综合起来,反而多赚了558元。
请根据这些信息计算:赔钱的那个价牌正确的价格应该是多少?
暴力枚举,就先枚举到赚了800多的情况,然后在这种情况下,暴力枚举到赔了200多的情况,然后两者相减,判断是不是558。
几点要考虑的
对于凑数:这两种情况发生在正看反过来都有意义的数,所以3,4,7可以不参与凑数过程。其次,原价为4位数,则凑数时千位不能为0。那就构造可以凑的数的数组,propNum[7] = {0,1,2,5,6,8,9}。四重循环,得原始数据。
对于翻转,只有6和9的情况会发生数字的变化,则依次判断是否为6或者9。每一位在一个if中判断,否则会出现,第一个if中判断,然后把6改成了9,然后再if就给改回去了的情况。。
9088
赚的吊盘:1061
#include
using namespace std;
int main() {
int propNum[7] = {0,1,2,5,6,8,9};
int org_E= 0 , exc_E = 0 , org_T = 0 , exc_T = 0;
int a,b,c,d;
for (int i = 1; i < 7; ++i) {
a = propNum[i];
for (int j = 0; j < 7; ++j) {
b = propNum[j];
for (int k = 0; k < 7; ++k) {
c = propNum[k];
for (int l = 0; l < 7; ++l) {
d = propNum[l];
org_E = a*1000+b*100+c*10+d;
if (a==6 || a==9){
if (a == 6) a=9;
else a = 6 ;
}
if (b==6 || b==9){
if (b == 6) b=9;
else b = 6 ;
}
if (c==6 || c==9){
if (c == 6) c=9;
else c = 6 ;
}
if (d==6 || d==9){
if (d == 6) d=9;
else d = 6 ;
}
exc_E = d*1000+c*100+b*10+a;
if(exc_E - org_E > 800 && exc_E-org_E <900){
// cout << org_E<<" "<
for (int m = 1; m < 7; ++m) {
a = propNum[m];
for (int n = 0; n < 7; ++n) {
b = propNum[n];
for (int i1 = 0; i1 < 7; ++i1) {
c = propNum[i1];
for (int j1 = 0; j1 < 7; ++j1) {
d = propNum[j1];
org_T = a*1000+b*100+c*10+d;
if (a==6 || a==9){
if (a == 6) a=9;
else a = 6 ;
}
if (b==6 || b==9){
if (b == 6) b=9;
else b = 6 ;
}
if (c==6 || c==9){
if (c == 6) c=9;
else c = 6 ;
}
if (d==6 || d==9){
if (d == 6) d=9;
else d = 6 ;
}
exc_T = d*1000+c*100+b*10+a;
if(org_T-exc_T > 200 && org_T-exc_T<300){
if((exc_E - org_E)-(org_T-exc_T)==558){
cout << org_T;
return 0;
}
}
}
}
}
}
}
}
}
}
}
}
X星系的机器人可以自动复制自己。它们用1年的时间可以复制出2个自己,然后就失去复制能力。
每年X星系都会选出1个新出生的机器人发往太空。也就是说,如果X星系原有机器人5个,
1年后总数是:5 + 9 = 14
2年后总数是:5 + 9 + 17 = 31
如果已经探测经过n年后的机器人总数s,你能算出最初有多少机器人吗?
输入:
输入一行两个数字n和s,用空格分开,含义如上。n不大于100,s位数不超过50位。
输出:
要求输出一行,一个整数,表示最初有机器人多少个。
输入: 2 31
输出:5
从有一个开始试,试到n年,看此时的结果是不是输入的总人数。是就输出并退出,不是的话就继续。
并没有oj可以测试,所以就猜着做,感觉可能会超时。。
s有50位,所以得设成longlong类型。
核心过程就是题目描述的,按照变量表示就可以了。今年能产生的机器人数量=去年的*2-1。然后爸今年产生的家在总count里。判断count和输入的一不一样。
#include
using namespace std;
int main() {
int n;
long long total,count = 0,thisYear=0,lastYear=0 ;
cin >> n >>total;
for (int i = 1; i < total; ++i) {
count = i; thisYear = i;
for (int j = 0; j < n; ++j) {
lastYear = thisYear;
thisYear = lastYear*2-1;
count+= thisYear;
}
if (count == total) {
cout << i;
return 0;
} else continue;
}
}
小明正看着 203879 这个数字发呆。 原来,203879 * 203879 = 41566646641这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。具有这样特点的6位数还有一个,请你找出它!
再归纳一下筛选要求:
输出:
输出这另一个数字
依次枚举,取得互不相同的6位数,平方,此时只有unsigned long long能存下,long long 也不行。然后%10 /10 依次判断是否出现在原始数组。通过一个bool的数组来完成。
每次循环把数组清空。要不然会带着上一次的结果。。
另写一个判断函数,不在主循环里判断是否有数字和原来相等,要不然break并不能跳出本次循环,枚举下一种情况,只能跳出while。
639172
#include
#include
using namespace std;
bool arr[10]={false};
bool judge(int a){
int temp;
unsigned long long res;
res = pow(a,2);
while (res!=0){
temp = res%10;
res = res/10;
if(arr[temp]) return false;
}
return true;
}
int main() {
int org,temp;
long long res;
int a,b,c,d,e,f;
for(a = 1 ; a < 10 ; a++){
for(b = 0; b < 10 ; b++){
for(c = 0 ; c < 10 ; c++){
for(d = 0 ; d < 10 ; d++){
for(e = 0 ; e < 10; e++){
for(f = 1 ; f < 10 ; f++){
if(a!=b && a!=c && a!=d && a!=e && a!=f &&
b!=c && b!=d && b!=e &&b!=f&&
c!=d && c!=e && c!=f &&
d!=e && d!=f &&
e!=f){
for (int i = 0; i < 10; ++i) {
arr[i] = false;
}
arr[a] = true;arr[b] = true;arr[c] = true;
arr[d] = true;arr[e] = true;arr[f] = true;
org = a*100000+b*10000+c*1000+d*100+e*10+f;
if(judge(org)){
cout << org<<endl;
break;
}
}
}
}
}
}
}
}
}
福尔摩斯从X星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为8的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
输入:
输入第一行:一个字符串s,全部由小写字母组成,长度小于1024*1024
紧接着一行是一个整数n,表示以下有n行密码,1<=n<=1000
紧接着是n行字符串,都是小写字母组成,长度都为8
输出:
一个整数, 表示每行密码的所有排列在s中匹配次数的总和。
输入:
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
输出:
4
首先看懂4是怎么来的。
子串1 aaaabbbb 可以匹配母串1-8位;子串变换为aaabbbba,匹配母串2-9位;子串变换为aabbbbaa,匹配母串3-10位置。
子串2 abcabccc,可以变换为aabbcccc,匹配母串最后8位。
所以一共4种情况。
子串无论怎么变化,字符个数不会发生变化。也就是子串1就是4个a,4个b。子串2就是2个a,2个b,4个c。子串匹配母串的某一位置,就是看在母串[x,x+8]的位置上是不是和子串有相同的字符数量。如果字符数量相同,那么子串一定可以通过某种排列方式变换为母串。
就像子串1是4个a,4个b,母串1-8位是4个a,4个b,那么子串一定可以变换从而匹配,count+1;母串2-9位也是4个a,4个b,那么子串同样可以变化进行匹配,以此类推 母串3-10位也可以,其余的不再匹配。子串2共有2个a,2个b,4个c,在母串最后8位是2个a,2个b,4个c,则子串2一定可以变换从而匹配。
那么,在这种思路下,处理每个子串行程一个int ziChar[26]的数组存储子串的各个字母的个数。枚举每一个母串的8位,形成一个int muChar[26]的数组存储母串截取的子串的字符个数,进行匹配比较,完全相同即可。
ps 我一开始的bug,遍历母串写的k < muString.length()-8,没有写等号,导致母串最后8位并没有截取到,导致第二种情况没有输出,debug时断点设的位置也不够好,一直以为cin没进去。。
#include
#include
using namespace std;
bool judge(int ziChar[26], int muChar[26]){
for (int i = 0; i < 26; ++i) {
if (ziChar[i] != muChar[i]) return false;
}
return true;
}
int main() {
string muString;
string ziString;
int n;
cin >>muString;
cin >>n;
int count = 0 ;
for (int i = 0; i < n; i++) {
cin >> ziString;
int ziChar[26] ={0};
//处理子串
for (int j = 0; j < 8; ++j) {
ziChar[ziString[j]-97]++;
}
//截取母串
for (int k = 0; k <= muString.length()-8; ++k) {
string s;
s = muString.substr(k,8);
//获取截取的母串的字母
int muChar[26]={0};
for (int p = 0; p < 8; ++p) {
muChar[s[p]-97]++;
}
//进行匹配
if (judge(ziChar,muChar)) {
// cout << "1"<
count++;
}
}
}
cout << count;
}
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838
输入:
程序输入为一个正整数N (N<5000000)
输出:
要求输出4个非负整数,按从小到大排序,中间用空格分开
从小到大枚举就肯定是按序的了。只管思路就是4重循环,但一定超市。最后一层d可以通过开平方求出来,所以可以省掉最后一层。算了一下5000000开平方事2236多,所以每层循环的最大值就设置为2237。非常直观但不知道oj上会不会超时。。
#include
#include
using namespace std;
int main() {
int n,temp;
int a,b,c;
double d;
cin >> n ;
for(a = 0 ; a < 2237; a++){
for(b = a ; b < 2237; b++){
for(c = b ; c < 2237; c++){
d = sqrt(n-a*a-b*b-c*c);
if(d == int(d)){
cout << a<<" "<<b<<" "<<c<<" "<<d;
return 0;
}
}
}
}
}
A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。 要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。请填写出所有符合要求的排列中,字典序最小的那个。
例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
构造 – 判断 --(存储)-- 输出
字典序最小就是 2 3 4 A的顺序。因为A是65,2是32。所以用5代替A。由于不熟悉string的库,所以方法比较蠢。。8重循环,枚举一个结果,再判断是不是符合4对牌的规则,就是2 3 4 5 各有两个。然后再判断数字的间隔和不合理。这样第一个输出就是字典序最小的。
8重循环实在是蠢。。搜了一下。可以利用string库的全排列函数,然后用find函数判断两个字母的位置是不是符合要求,是就存到set里(自带排序),然后直接输出头。
2342A3A4
#include
#include
#include
using namespace std;
int s[8]={0};
bool count(int s[8]){
int arr[6] = {0};
for (int i = 0; i < 8; ++i) {
arr[s[i]]++;
}
if(arr[2] == arr[3] && arr[3]== arr[4]&& arr[4] == arr[5]&&arr[5]==2) return true;
else return false;
}
bool judge(int a, int b){//a代表牌 b代表间隔
int i = 0 ;
while(s[i] != a){i++;}
if(s[i] == s[i+b+1]){ return true;}
else return false;
}
int main() {
int a,b,c,d,e,f,g,h;
for(a = 2; a <=5 ; a++){
s[0] = a;
for(b = 2; b<=5; b++){
s[1] = b;
for(c = 2; c <=5 ; c++){
s[2] = c;
for(d = 2; d<=5; d++){
s[3] = d;
for(e = 2 ; e <=5; e++){
s[4] = e;
for(f = 2; f <=5 ; f++){
s[5] = f;
for(g = 2; g<=5 ; g++){
s[6] = g;
for(h = 2 ; h <=5 ; h++){
s[7] = h;
if(count(s)){//数量合格
// cout<
if(judge(5,1)&&judge(2,2)&&judge(3,3)&&judge(4,4)){
cout<<a<<b<<c<<d<<e<<f<<g<<h<<endl;
}
}
}
}
}
}
}
}
}
}
}
#include
#include
#include
using namespace std;
int main() {
string s = "223344AA";
set<string> sSet;
do{
unsigned long beginA = s.find('A',0);
unsigned long endA = s.find('A',beginA+1);
unsigned long begin2 = s.find('2',0);
unsigned long end2 = s.find('2',begin2+1);
unsigned long begin3 = s.find('3',0);
unsigned long end3 = s.find('3',begin3+1);
unsigned long begin4 = s.find('4',0);
unsigned long end4 = s.find('4',begin4+1);
if(endA-beginA == 2 && end2-begin2 == 3&& end3-begin3 ==4 &&end4-begin4 == 5){
sSet.insert(s);
}
}while(next_permutation(s.begin(),s.end()));
set<string>::iterator it=sSet.begin();
cout << *it <<endl;
}
find(‘’, )第一个位置是字符,第二个位置是起始位置,一定要在begin后+1,要不然就是begin的位置,不会变化。。
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入:
两个正整数,表示每种包装中糖的颗数(都不多于1000)
输出:
一个正整数,表示最大不能买到的糖数
输入 4 7
输出 17
思路是并没有什么思路。。虽然觉得枚举一定可行,但是连续出现多少个就能认为后面的都连续了呢?感觉需要数学证明。可以想到的就是 输入的两个数一定互质。然后好像输出的数据也是质数?然后搜了一下就
a*b-a-b 就可以了。。没看到证明。
#include
using namespace std;
int main() {
int a,b;
cin >> a>>b;
cout << a*b-a-b<<endl;
}
A 村的元宵节灯会上有一迷题: 请猜谜 * 请猜谜 = 请边赏灯边猜 小明想,一定是每个汉字代表一个数字,不同的汉字代表不同的数字。 请你用计算机按小明的思路算一下,然后输出“请猜谜”三个字所代表的整数即可。
输入:
不需要输入
输出:
输出“请猜谜”三个字所代表的整数即可。
请猜谜 分别设为ABC,请边赏灯边猜为ADEFDB,其中ABCDEF均不等。三重循环枚举ABC,乘方得结果,判断是不是六位数,再判断数字是不是合法。
#include
using namespace std;
int a,b,c,d1,d2,e,f;
bool judge(int ans){
int a1,b1;
b1 = ans%10;
if(b1 != b) return false;
ans = ans/10;
d2 = ans%10;ans = ans/10;
f = ans%10; ans = ans/10;
e = ans%10; ans = ans/10;
d1 = ans%10; ans = ans/10;
a1 = ans%10;
if(d1 !=d2) return false;
if(a1!=a) return false;
if(e!=f && e!= a && e!=b && e!=c &&e!=d1 &&f!=a && f!=b && f!=c && f!=d1) return true;
}
int main() {
int ans,org;
for(a = 1; a <= 9 ; a++){
for(b = 0 ; b<= 9 ; b++){
for(c = 2; c <=9 ; c++){
if(a !=b && a!=c && b!=c){
org = a*100+b*10+c;
ans = org*org;
if(ans > 100000 && ans < 999999){
if(judge(ans)){
cout << org<<endl;
}
}
}
}
}
}
}
①输入正整数n(如62),2<=n<=79;
②输出形如abcde/fghij=n的表达式,每行输出一个表达式,其中a ~ j 恰好为0~9的一种排列;
输入:62
输出:
79546/01283=62
94736/01528=62
第一反应 全排列,挨个除,显然复杂度过高。此题和四平方问题相同,都是可以用其余几个变量求出另一个变量。从而降低复杂度。
输入的num和a相乘可以得到b,表示的时候为b/a = num。由于是全排列,且前后都是五位,那么对于a来说最小为01234,最大为98765,那么就用a*num得b之后判断a和b是否唯一即可。
在判断a和b是否唯一的时候,重点是0的问题。在做%10和/10的时候,4位数隐藏的0并不会被记入。也就意味着a为四位数,b中含有0的时候,按照标准不可行,但是单纯的%10和/10会忽略掉a隐藏的0,让判断结果成了可行。所以应首先判断a和b是否为4位数,是的话首先将代表0的arr[0]加一。
输出使用printf格式化输出进行补0。
#include
using namespace std;
bool judge(int a, int b){
int arr[10]={0};
int temp;
if(a >1000 && a <9999){arr[0]++;}
if(b >1000 && b <9999){arr[0]++;}
while(a!=0){
temp = a%10;
a = a/10;
arr[temp]++;
}
while (b!=0){
temp = b%10;
b = b/10;
arr[temp]++;
}
for (int i = 0; i < 10; ++i) {
if(arr[i] != 1) return false;
}
return true;
}
int main() {
int n;
cin >> n ;
int a , b;
for(a = 1234; a <= 98765 ; a++){
b = a * n;
if(judge(a,b)){
printf("%05d/%05d = %d\n",b,a,n);
}
}
}