怎么说呢,今天无聊就刷了一下蓝桥杯的题目,毕竟也参加了两届,虽然每次运气都很差。。。坑的一比, 废话不多说,今天刚好看了一下往届的比赛题目,偶然发现一题感觉思路一看就有,但是无从下手的题目, 没错,就像你搜的这样子,这道题目的名字就是“带分数”。
刚刚开始做的时候,直接就是一股劲的爆搜,看了看时间复杂度,估计超时不超时是五五开,就是将1-9这 9个数字进行全排列, 这个时间的复杂度是10!,用到了stl的一个全排列函数,叫做next_permutation, 想要了解更多的各位大大或者是萌新可以自己去百度一下这个的用法就是了,毕竟我们这个博客的主题还 是要针对这题题目来写的。 虽然这个想法很危险,很容易超时。。。。但是好歹写出来再说,经过半小时的编程,我就蛋疼了,连 样例都是过不了的,于是ctrl + a,然后删除,直接推倒重写,这次估计了一下复杂的有美酒先 将这个数字表示为v = a + b / c;所以a肯定比v小,那么最外层就可以确定了,然后将 a进行拆分,进行判断,之后就是将没用到的数字存放在一个数组里面,利用stl的全排列,然后将之 后的数字进行组合,由于b/c这个形式,感觉就是b要比c大,同时整除,这时候又是一重剪枝,大概 的时间复杂度没去算过,反正提交一发,1a之后表示就没有去算过
下面是具体的事实表明可以,以及附上ac代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int main(){ int v, ans = 0; bool vis[11]; scanf("%d", &v); for(int a=1; a<v; a++){ int m = a, f = 0; memset(vis, false, sizeof(vis)); while(m){// 判断当前数字之中的1-9只出现了一次 if(vis[m%10] == true || m % 10 == 0){ f = 1; break; }else{ vis[m%10] = true; m /= 10; } } if(f == 0){ int len = 0, num[10]; for(int i=1; i<=9; i++) if(vis[i] != true) num[len++] = i; while(next_permutation(num, num + len)){// 对剩下的数字进行全排列 int mid = (len - 1) / 2, bg = 9 - len; int b = 0; for(int i=0; i<mid; i++) b = b * 10 + num[i]; for(int i=mid; i<len-1; i++){ b = b * 10 + num[i]; int c = 0; for(int j=i+1; j<len; j++) c = c * 10 + num[j]; if(b < c) continue; if(b % c == 0 && a + b / c == v){// 满足条件时候,计数器自加1 ans++; // printf("%d %d %d ", a, b, c); } } } } } printf("%d ", ans); return 0; }