【蓝桥杯】幸运数
2014-03-08 16:24
204 查看
算法思想:类比素数打表, 但是速度很慢
#include<iostream> #include<cstdio> using namespace std; int a[500000 + 1]; int m, n; void lucky(int start, int len) { int k = start, num = a[start]; for(int i = k; i < len; i++) { if(i % num != 0) { a[k++] = a[i]; } } if(num < len && a[start + 1] < n) { lucky(start + 1, k); } } int main() { cin >> m >> n; int len = 500000, kinds = 0; for(int i = 1; i < len; i++) a[i] = 2 * i - 1; lucky(2, len); for(int i = 1; i < len; i++) { if(a[i] >= n || a[i] == a[i - 1]) { break; } if(a[i] > m && a[i] < n) { kinds++; } } cout << kinds; return 0; }
另一个犇给的代码,我进行了注释,注释可能有措辞不当的地方请自行脑补
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> using namespace std; const int maxn = 1000010; bool flag[maxn]; //用于标记是不是幸运数 int m, n; //记录范围的m, n int a[maxn], s[maxn], size = 0; //数组a存储幸运数i的位置(幸运数列中的) int fa(int k) { //用于寻找幸运数的个数 if( flag[k] ) { return a[k]; } return fa(k - 1); } int main() { cin >> m >> n; for(int i = 1; i <= n; i += 2) { s[++size] = i; //数组s存储幸运数列 flag[i] = true; //数组flag表示数字i是不是幸运数 a[i] = size; //a[i]存储了i之前(包括i)的幸运数的个数 } for(int i = 2; i <= size; i++) { int mod = s[i], d = s[i] - 1; //mod是原来幸运数序列的第i个数 if(mod > size) { break; } for(int p = 1, j = mod; j <= size; j += mod, p++) { //因为每次删除的都是j到2j的非幸运数,但是没有删除2j到3j的,为此每删除一轮,p自增一次 flag[ s[j] ] = false; //mod的倍数一定不是幸运数,标记删去 for(int k = 1; k < mod && k + j <= size; k++) { //k < mod, 故k + j < 2 * mod s[++d] = s[j + k]; //更新幸运数序列 a[ s[j + k] ] -= p; //s[j + k]之前的幸运数个数减少p个 } } size = d; //更新幸运数序列长度 } printf("%d", fa(n - 1) - fa(m)); //幸运数个数相减,即是从 m 到 n - 1的幸运数个数 return 0; }
相关文章推荐