51nod一级算法题全部题解
2017-05-10 15:47
183 查看
51nod一级算法题
1001数组中和等于k的数对:对数组排序,枚举其中一个数,然后二分对应的另一个数。1002数塔取数问题:初等的动态规划,自底向上进行更新就好。
1003阶乘后面0的数量:分析可以发现,只需要统计5,5^2,5^3...的倍数在n中出现的次数,最后相加就是结果。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 5*1e4+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int n; int arr[Max]; int main( ) { //freopen("input.txt", "r", stdin); while(~scanf("%d", &n)) { int ans = 0; ll k = 5; while(n/k) { ans += n/k; k *= 5; } cout<<ans<<endl; } return 0; }
1004n^n的末位数字:末位数字只和末位数字有关,简单的快速幂即可解,logn的复杂度。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 5*1e4+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int n; int arr[Max]; int main( ) { //freopen("input.txt", "r", stdin); while(~scanf("%d", &n)) { int k = n%10; int ans = k, t = 1; while(n>1) { if(n%2) t = (t*ans)%10; ans = (ans*ans)%10; n /= 2; } ans = (ans*t)%10; cout<<ans<<endl; } return 0; }
1009数字1的数量:将数拆分为位,统计每一位出现1的数量,最后加和。当该位为1时,该位出现的数字1数量等于该位高位数字组成的数乘以本位的权重再加上低位数字组成的数加一; 当该位不为1时候,为0的话,等于高位数乘以本位权重,大于一的话等于高位数加一乘以本位权重。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 1e6+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int n; int main( ) { //freopen("input.txt", "r", stdin); while(~scanf("%d", &n)) { int ans= 0; int i=1, current=0, before = 0, after = 0; while(n/i != 0) { current = (n/i)%10; before = n/(10*i); after = n%i; if(current == 0) ans += before*i; else if(current == 1) ans += before*i+after+1; else ans += (before+1)*i; i *= 10; } cout<<ans<<endl; } return 0; }
1015水仙花数:由于输入数据的范围,可以取巧只算出1000以内的水仙花数和1000以外的一个水仙花数,然后对于每次询问查询即可。
1080两个数的平方和:枚举到sqrt(n)即可
1082与7无关的数:用数组预先计算好n以内的所有结果,然后查询,不会超时。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 1e6+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int ans; int T, n, m; ll arr[Max]; bool relate7(int a) { int k = 1e6; while(a/k==0) k /= 10; for(; k>0; k/=10) { int t = a/k; if(t == 7) return true; a -= t*k; } return false; } int main( ) { //freopen("input.txt", "r", stdin); for(ll i=1; i<Max; i++) { if(i%7 && !relate7(i)) arr[i] = arr[i-1]+i*i; else arr[i] = arr[i-1]; } scanf("%d", &T); while(T--) { scanf("%d", &n); printf("%lld\n", arr ); } return 0; }
1083矩阵取数问题:基础动态规划
1087 1 10 100 1000:发现1总是位于n(n+1)/2,二分求解输入是否可能为该式的计算结果,其中n只能取整数,可以就是1,不可以就是0。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 1000; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; ll n, m, T; ll f(ll n) { return (n+1)*n/2; } int main( ) { //freopen("input.txt", "r", stdin); scanf("%lld", &T); while(T--) { scanf("%lld", &n); if(n==1 || n==2) { cout<<1<<endl; continue; } n--; ll low=1, high = 1e9, flag = 0; while(low <= high) { ll mid = (low+high)>>1; if(f(mid) == n) { flag = 1; break; } else if(f(mid)>n) high = mid-1; else low = mid+1; } if(flag) cout<<1<<endl; else cout<<0<<endl; } return 0; }
1090 3个数和为0:枚举其中两个,二分最后一个。
1091线段的重叠:贪心,优先选取左端点小的。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 5*1e4+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int T,n,m; bool cmp(const pair<int ,int>& a, const pair<int,int>& b) { if(a.first != b.first) return a.first<b.first; return a.second<b.second; } int main( ) { //freopen("input.txt", "r", stdin); pair<int, int> line[Max]; while(~scanf("%d", &n)) { int a, b; for(int i=0; i<n; i++) { scanf("%d%d", &a, &b); line[i].first = min(a, b); line[i].second = max(a, b); } sort(line, line+n, cmp); int ans = 0; int temp = line[0].second; for(int i=1; i<n; i++) { if(line[i].first>=temp) temp = line[i].second; else if(line[i].second > temp) { ans = max(ans, temp-line[i].first); temp = line[i].second; } else ans = max(line[i].second-line[i].first, ans); } cout<<ans<<endl; } return 0; }
1182完美字符串: 基础的贪心
1283最小周长:数学知识,基本不等式。
1284 2 3 5 7的倍数:包含排斥原理。
#include<iostream> #include<cstring> #include<math.h& 4000 gt; #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 1e6+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int T,n,m; ll f(ll n) { ll a = n/2 + n/3 + n/5 + n/7; ll b = n/6 + n/10 + n/14 + n/15 + n/21 + n/35; ll c = n/30 + n/42 + n/70 + n/105; ll d = n/210; return n-a+b-c+d; } int main( ) { //freopen("input.txt", "r", stdin); ll n; while(~scanf("%lld", &n)) { ll ans = f(n); cout<<ans<<endl; } return 0; }
1289大鱼吃小鱼:很有意思的模拟,详见代码。
#include<iostream> #include<cstring> #include<math.h> #include<stdlib.h> #include<cstring> #include<cstdio> #include<utility> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int Max = 1e6+5; const int mod = 1e9+7; const int Hash = 10000; const int INF = 1<<30; int T,n,m; int main( ) { //freopen("input.txt", "r", stdin); while(~scanf("%d", &n)) { ll ans = 0; int heavy[Max], dir[Max]; for(int i=0; i<n; i++) scanf("%lld%lld", heavy+i, dir+i); int big = 0; for(int i=0; i<n; i++) { if(dir[i]==0 && heavy[i]>big) { ans++; big = 0; } else if(dir[i]==1) big = max(big, heavy[i]); } big = 0; for(int i=n-1; i>=0; i--) { if(dir[i]==1 && heavy[i]>big) { ans++; big = 0; } else if(dir[i]==0) big = max(big, heavy[i]); } cout<<ans<<endl; } return 0; }
1305Pairwise Sum and Divide:模拟水题。
1344走格子:模拟水题。
1347旋转字符串:分析一下,符合的一定是偶数长度,并且前半段和后半段相等的串。
1381硬币游戏:数学问题,每两条直线的间距都是1,所以期望显然就是圆的直径长度除以1,就是2R
相关文章推荐
- 51nod二级算法题全部题解
- 算法(第四版)C# 习题题解——1.3.49 用 6 个栈实现一个 O(1) 队列
- 设计一个算法,输出从u到v的全部最短路径(採用邻接表存储)
- 2018年全国多校算法寒假训练营练习比赛(第四场) 比赛题目题解
- 珍藏版、微软等数据结构+算法面试100题全部出炉
- 【暴力搜索】【莫队算法】【贪心】[Codeforces Round #340 (Div. 2) ]题解报告
- 微软等数据结构+算法面试100题全部答案集锦
- 微软等数据结构+算法面试100题全部答案完整亮相
- 获取两个字符串全部公共的子串算法
- 找到一个二维矩阵中所有包含0的,并且把0元素所在行与列全部转换成0的算法!
- 算法提高 学霸的迷宫 (题解)
- 微软等数据结构+算法面试100题全部答案集锦 复制过来比较乱
- 洛谷3805:【模板】manacher算法——题解
- 【BZOJ】【P2038】【小Z的袜子】【题解】【莫队算法】
- 整数算法训练04—求100以内的素数,全部打印出来
- 牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) 题解
- 2018年全国多校算法寒假训练营练习比赛(第五场)题解
- 全部博文集锦第三期CHM文件,及十三个经典算法研究PDF文档
- 总结一个随机抽取算法(全部item出现概率和为100%)
- POJ 1847 全部算法 图论