[蓝桥杯][2013年第四届真题]幸运数
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成
。
首先从1开始写出自然数1,2,3,4,5,6,....
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
1 _ 3 _ 5 _ 7 _ 9 ....
把它们缩紧,重新记序,为:
1 3 5 7 9 .... 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, ...
此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,...)
最后剩下的序列类似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...
。
首先从1开始写出自然数1,2,3,4,5,6,....
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
1 _ 3 _ 5 _ 7 _ 9 ....
把它们缩紧,重新记序,为:
1 3 5 7 9 .... 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, ...
此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,...)
最后剩下的序列类似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...
输入
输入两个正整数m n, 用空格分开 (m < n < 1000*1000)
输出
程序输出 位于m和n之间的幸运数的个数(不包含m和n)。
样例输入
30 69
样例输出
8
具体用到了对vector数组的操作
#include <iostream> #include<bits/stdc++.h> using namespace std; vector<int>a; int del(int i) { int j=a[i],v=a[i]; int n=a.size(); while(j<n) { j+=v; } for(int k=j-v;k>=v;k-=v) a.erase(a.begin()+k); } int main() { int m,n,i; cin>>m>>n; for(i=0;i<n;i++) a.push_back(i); del(2); for(i=2;i<n;i++) del(i); int ans=0; for(i=0;i<a.size();i++) { if(a[i]>m) ans++; } cout<<ans<<endl; return 0; }
问题 1456: [蓝桥杯][历届试题]连号区间数
题目描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入
第一行是一个正整数N (1 < = N < = 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 < = Pi < = N), 表示这N个数字的某一全排列。
第二行是N个不同的数字Pi(1 < = Pi < = N), 表示这N个数字的某一全排列。
输出
输出一个整数,表示不同连号区间的数目。
样例输入
5 3 4 2 5 1
样例输出
9
很巧妙的一种思维方式
#include <iostream> #include<bits/stdc++.h> using namespace std; int a[50005]; int main() { int n,i,j; cin>>n; for(i=1;i<=n;i++) cin>>a[i]; int ans=0; for(i=1;i<=n;i++) { int minn=50005,maxx=0; for(j=i;j<=n;j++) { if(a[j]>maxx) maxx=a[j]; if(a[j]<minn) minn=a[j]; if(maxx-minn==abs(j-i)) { ans++; } } } cout<<ans<<endl; return 0; }
完美的代价
题目描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入
第一行是一个整数N,表示接下来的字符串的长度(N < = 8000)
第二行是一个字符串,长度为N.只包含小写字母
第二行是一个字符串,长度为N.只包含小写字母
输出
如果可能,输出最少的交换次数。
否则输出Impossible
否则输出Impossible
样例输入
5 mamad
样例输出
3
利用贪心的思想,将每个遍历的字符找到后面与他相同的然后交换到正确的位置时所需的交换次数,if(k==i)说明没有找到与a[i]相同的字符
#include <iostream> #include<bits/stdc++.h> using namespace std; int vis[26]; int main() { int n,i,k; cin>>n; string s; cin>>s; int j=n-1; int flag=0; int cnt=0; for(i=0;i<j;i++) { for(k=j;k>=i;k--) { if(k==i) { if(n%2==0||flag) { cout<<"Impossible"<<endl; return 0; } flag=1; cnt+=n/2-i; } else if(s[i]==s[k]) { for(int v=k;v<j;v++) { swap(s[v],s[v+1]); cnt++; } j--; break; } } } cout<<cnt<<endl; return 0; }