OJ刷题总结
NOJ1009 2的n次方
模拟小学时候的竖乘,注意code中extra变量的位置
#include <iostream>
using namespace std;
const int N = 1000;
int n, a[N];
int main()
{
int k = 1;
cin >> n;
a[1] = 1;
for(int i = 1; i <= n; i++ )
{
int extra = 0;
for(int j = 1; j <= k; j++ )
{
a[j] = (a[j] << 1) + extra;
extra = a[j] / 10;
a[j] %= 10;
if(extra != 0 && j == k) k++;
}
}
for(int i = k; i >= 1; i-- )
printf("%d", a[i]);
puts("");
return 0;
}
5.NOJ1011 大数加法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
string s1, s2;
int a[N], b[N];
int ans[N];
void switch_toint(string s, int u[])
{
for(int i = 0; i < s.length(); i++ )
u[i] = s[s.length() - i - 1] - '0';
}
int main()
{
cin >> s1 >> s2;
switch_toint(s1, a);
switch_toint(s2, b);
int edge = max(s1.length(), s2.length());
for(int i = 0; i < edge; i++ )
{
ans[i] += a[i] + b[i];
ans[i + 1] = ans[i] / 10;
ans[i] %= 10;
}
if(ans[edge])
printf("%d", ans[edge]);
for(int i = edge - 1; i >= 0; i-- )
printf("%d", ans[i]);
puts("");
return 0;
}
NOJ1012 进制转换
特别基础的题,就是因为忘记特判n == 0 然后wa卡了5分钟,要认真审题要认真审题要认真审题
#include <iostream>
#include <cstdio>
using namespace std;
char a[17] = "0123456789ABCDEF";
void dfs(int n, int r)
{
if(!n) return;
dfs(n / r, r);
cout << a[n % r];
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n, r;
scanf("%d%d", &n, &r);
if(n < 0) cout <<'-';
if(!n){cout << '0' << endl; continue;}
dfs(abs(n), r);
puts("");
}
return 0;
}
NOJ1142 最大连续和
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
LL a[N], s[N];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int m;
scanf("%d", &m);
memset(s, 0, sizeof s);
for(int i = 1; i <= m; i++ )
{
scanf("%lld", a + i);
s[i] = s[i - 1] + a[i];
}
LL res = -1e10;
for(int i = 0; i <= m; i++ )
for(int j = i + 1; j <= m; j++ )
res = max(res, s[j] - s[i]);
printf("%lld
", res);
}
return 0;
}
NOJ1094 蛇形填数
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 70;
int a[N][N];
int main()
{
int n, k = 1;
cin >> n;
int i = 0, j = n - 1;
a[i][j] = 1;
while(k < n * n)
{
while(a[i + 1][j] == 0 && i <= n - 2) a[++i][j] = ++k;
while(a[i][j - 1] == 0 && j >= 1) a[i][--j] = ++k;
while(a[i - 1][j] == 0 && i >= 1) a[--i][j] = ++k;
while(a[i][j + 1] == 0 && j <= n - 2) a[i][++j] = ++k;
}
for(int i = 0; i < n; i++ )
{
for(int j = 0; j < n; j++ )
printf("%5d", a[i][j]);
cout << endl;
}
return 0;
}
HDU1009 FatMouse Trade
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
struct room
{
int jb, cf;
double rate;
bool operator< (const room & t)const
{
return rate > t.rate;
}
}g[N];
int m, n;
int main()
{
while(scanf("%d%d", &m, &n), m + 1)
{
for(int i = 0; i < n; i++ )
{
scanf("%d%d", &g[i].jb, &g[i].cf);
g[i].rate = g[i].jb * 1.0 / g[i].cf;
}
sort(g, g + n);
double sum = 0;
for(int i = 0; i < n; i++ )
{
if(m <= 0) break;
if(m >= g[i].cf)
{
sum += g[i].jb;
m -= g[i].cf;
continue;
}
if(m < g[i].cf && m > 0)
{
sum += g[i].rate * m;
m = 0;
}
}
printf("%.3lf
", sum);
}
return 0;
}
-
一些字符串处理的问题
HDU2072 单词数
计算不重复的单词出现个数,很容易想到set容器,然后用stringstream处理字符流输出set的尺寸即为答案
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <sstream>
using namespace std;
int main()
{
string s;
while(getline(cin, s), s != "#")
{
set<string> words;
stringstream ssin(s);
string u;
while(ssin >> u)
words.insert(u);
cout << words.size() << endl;
}
return 0;
}
HDU2081 手机短号
通过stringstream来实现字符串与整数间的转换
#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <sstream>
using namespace std;
typedef long long LL;
int main()
{
int t;
cin >> t;
while(t--)
{
string s;
LL res;
cin >> s;
stringstream ssin(s);
ssin >> res;
printf("%lld
", 600000 + res % 100000);
}
return 0;
}
NOJ1023 字符串排序
题目表述有歧义,,,
比较基础的一题,重载一个运算符就可以ac
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<string, int> PSI;
const int N = 1e5 + 10;
PSI str[N];
int cnt(string s)
{
int res = 0;
for(auto x : s)
if(x == 'A') res++;
return res;
}
bool cmp(const PSI & s1, const PSI & s2)
{
if(cnt(s1.x) < cnt(s2.x)) return true;
else if(cnt(s1.x) > cnt(s2.x)) return false;
else
{
if(s1.y < s2. y) return true;
else return false;
}
}
int main()
{
int res = 1;
while(cin >> str[res].x)
{
str[res].y = res;
res++;
}
sort(str + 1, str + res, cmp);
for(int i = 1; i < res; i++ )
cout << str[i].x << endl;
return 0;
}
HDU2602 01背包问题
简单的dp,
DP核心就是状态表示 + 状态计算(即寻找状态转移方程)
数组的某个元素表示的是某个选法的所有集合,存放的值即元素的属性是我们所需要的,一般分为三类(max, min, cnt)一般从最后一步来思考状态转移方程。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 1010;
int main()
{
int t;
cin >> t;
while(t--)
{
int n, m;
int v[N], w[N];
int f[N][N];
memset(f, 0, sizeof f);
cin >> n >> m;
for(int i = 1; i <= n; i++ )
cin >> w[i];
for(int i = 1; i <= n; i++ )
cin >> v[i];
for(int i = 1; i <= n; i++ )
for(int j = 0; j <= m; j++ )
{
f[i][j] = f[i - 1][j];
if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
}
cout << f[n][m] << endl;
}
return 0;
}
HDU1003 Max sum
第一遍写的dp,内存过大,超时
状态转移方程想的太过复杂,写出来就像是暴力算法,不可取。
正确的状态转移方程sum[i - 1] >= 0 ? sum[i] = sum[i - 1] + a[i] : sum[i] = 0;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N], f[N][N];
int main()
{
int t;
scanf("%d", &t);
for(int u = 1; u <= t; u++ )
{
int m, res = 0;
memset(f, 0, sizeof f);
scanf("%d", &m);
for(int i = 1; i <= m; i++ ) scanf("%d", a + i);
for(int i = 1; i <= m; i++ )
for(int j = i; j <= m; j++ )
{
f[i][j] = f[i][j - 1] + a[j];
res = max(res, f[i][j]);
}
int flag = 1;
for(int i = 1; i <= m && flag; i++ )
for(int j = 1; j <= m; j++ )
if(f[i][j] == res)
{
printf("Case %d:
", u);
printf("%d %d %d
", f[i][j], i, j);
flag = 0;
break;
}
}
return 0;
}
//ACcode
//from csdn
#include<stdio.h>
int main()
{
int n,m,t,i,j;
scanf("%d",&t);
int num=1;
while(t--)
{
int max=-9999;
int sum=0;
int begin=1,end=1,x=1;
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&m);
sum+=m;//记录最大连续和的值
if(sum>max)
{
max=sum;
begin=x;//记录开始于第几个数
end=i+1;//记录结束于第几个数
}
if(sum<0)//都是负数的情况
{
x=i+2;//注意:这时候是从下一个输入的数开始计算
sum=0;
}
}
if(num!=1)
printf("
");//注意输出格式
printf("Case %d:
",num++);
printf("%d %d %d
",max,begin,end);
}
return 0;
}
NOJ1030 ACM程序设计之马拉松竞赛
被空格卡的难受
因为第一遍代码写的不够周全,被一个刚开始没想到的样例卡了好久。
1.全部领奖 2.全部不领奖
HDU1166 敌兵布阵
wa的代码输入方式和ac的不一样,要注意!
考察树状数组,难度较小
//WAcode
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 50010;
int tr[N];
int n, val;
int lowbit(int x)
{
return x & -x;
}
int query(int x)
{
LL res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
void add(int x, int v)
{
for(int i = x; i <= n; i += lowbit(i)) tr[i] += v;
}
int main()
{
int t;
scanf("%d", &t);
for(int u = 1; u <= t; u++ )
{
memset(tr, 0, sizeof tr);
scanf("%d", &n);
for(int i = 1; i <= n; i++ )
{
scanf("%d", &val);
add(i, val);
}
printf("Case %d:
", u);
string c;
int j, k;
while(cin >> c >> j >> k && c[0] != 'E')
{
if(c[0] == 'Q')
cout << query(k) - query(j - 1) << endl;
else if(c[0] == 'A')
add(j, k);
else if(c[0] == 'S')
add(j, -k);
}
}
return 0;
}
//ACcode
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 50010;
int tr[N];
int n, val;
int lowbit(int x)
{
return x & -x;
}
int query(int x)
{
LL res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
void add(int x, int v)
{
for(int i = x; i <= n; i += lowbit(i)) tr[i] += v;
}
int main()
{
int t;
scanf("%d", &t);
for(int u = 1; u <= t; u++ )
{
memset(tr, 0, sizeof tr);
scanf("%d", &n);
for(int i = 1; i <= n; i++ )
{
scanf("%d", &val);
add(i, val);
}
printf("Case %d:
", u);
char c[10];
int j, k;
scanf("%s", c);
while(c[0] != 'E')
{
if(c[0] == 'Q')
{
scanf("%d%d", &j, &k);
cout << query(k) - query(j - 1) << endl;
}
else if(c[0] == 'A')
{
scanf("%d%d", &j, &k);
add(j, k);
}
else if(c[0] == 'S')
{
scanf("%d%d", &j, &k);
add(j, -k);
}
scanf("%s", c);
}
}
return 0;
}