2000题解:
#include <iostream>
#include <string>//hduoj中要用string
using namespace std;
int main()
{
string s;
while(cin >> s)
{
if(s[0] > s[1]) swap(s[0], s[1]);
if(s[1] > s[2]) swap(s[1], s[2]);
if(s[0] > s[1]) swap(s[0], s[1]);
cout << s[0] << ' ' << s[1] << ' ' << s[2] << endl;
}
return 0;
}
2001题解:
#include <iostream>
#include <string>//hduoj中要用string
#include <cmath>
using namespace std;
int main()
{
float x, y, a, b;//题目中没说是整数!
while(cin >> x >> y >> a >> b)
{
double dist = sqrt((a - x) * (a - x) + (b - y) * (b - y));
printf("%.2lf\n", dist);
}
return 0;
}
2002题解:
#include <iostream>
#include <string>
#include <cmath>
const double pai = 3.1415927;
using namespace std;
int main()
{
double x;//尽量都用double类型,别用float
while(cin >> x)
{
printf("%.3lf\n", 4.0 / 3 * pai * pow(x, 3));
}
return 0;
}
2003题解:
#include <iostream>
using namespace std;
int main()
{
double x;
while(scanf("%lf", &x) != EOF)
{
printf("%.2lf\n", abs(x));
}
return 0;
}
2004题解:
#include <iostream>
using namespace std;
int main()
{
int x;
while(scanf("%d", &x) != EOF)
{
if(x >= 90 && x <= 100) puts("A");
else if(x >= 80 && x <= 89) puts("B");
else if(x >= 70 && x <= 79) puts("C");
else if(x >= 60 && x <= 69) puts("D");
else if(x >= 0 && x <= 59) puts("E");
else puts("Score is error!");
}
return 0;
}
2005题解:闰年的判断:四年一闰,百年不闰,四百年一闰;(闰年2月为29天)
#include <iostream>
#include <string>
using namespace std;
int mon[14];
bool check(int x)
{
if(x % 4 == 0 && x % 100 != 0 || x % 400 == 0) return true;
return false;
}
int main()//判断闰年
{
for(int i = 1; i <= 12; i ++)
{
if(i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
mon[i] = 31;
else mon[i] = 30;
}
int year, month, day;
while(scanf("%d/%d/%d", &year, &month, &day) != EOF)
{
if(check(year)) mon[2] = 29;
else mon[2] = 28;
int res = 0;
for(int i = 1; i < month; i ++)
{
res += mon[i];
}
res += day;
cout << res << endl;
}
return 0;
}
2006题解:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
int res = 1;
while(n --)
{
int x;
cin >> x;
if(x % 2 != 0) res *= x;
}
cout << res << endl;
}
return 0;
}
2007题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()
{
int a, b;
while(cin >> a >> b)
{
if(a > b) swap(a, b);
int res_one = 0, res_two = 0;
for(int i = a; i <= b; i ++)
{
if(i % 2 == 0) res_one += pow(i, 2);
else res_two += pow(i, 3);
}
cout << res_one << ' ' << res_two << endl;
}
return 0;
}
2008题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
if(n == 0) break;
int neg = 0, pos = 0, zero = 0;
while(n --)
{
double x;
cin >> x;
if(x < 0) neg ++;
else if(x > 0) pos ++;
else zero ++;
}
cout << neg << ' ' << zero << ' ' << pos << endl;
}
return 0;
}
2009题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()
{
double n, m;
while(cin >> n >> m)
{
double res = n;
m --;
while(m --)
{
n = sqrt(n);
res += n;
}
printf("%.2lf\n", res);
}
return 0;
}
2010题解:
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
using namespace std;
bool check(int x)
{
int s = x, sum = 0;
while(s > 10)
{
sum += pow(s % 10, 3);
s = s / 10;
}
sum += pow(s, 3);
if(sum == x) return true;
else return false;
}
int main()
{
int m, n;
while(cin >> m >> n)
{
vector<int> res;
for(int i = m; i <= n; i ++)
if(check(i)) res.push_back(i);
if(res.size())
{
cout << res[0];
for(int i = 1; i < res.size(); i ++) cout << ' ' << res[i];
cout << endl;
}
else puts("no");
}
return 0;
}
2011题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()//奇数正 偶数负
{
int m;
cin >> m;
while(m --)
{
int n;
cin >> n;
double sum = 0;
for(int i = 1; i <= n; i ++)
{
if(i % 2 == 0) sum -= 1.0 / i;
else sum += 1.0 / i;
}
printf("%.2lf\n", sum);
}
return 0;
}
2012题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
bool check(int x)
{
if(x == 1) return false;
for(int i = 2; i < x / i; i ++)
if(x % i == 0) return false;
return true;
}
int main()
{
int x, y;
while(cin >> x >> y)
{
if(!x && !y) break;
bool success = true;
for(int i = x; i <= y; i ++)
{
if(!check(i * i + i + 41)) success = false;
}
if(success) puts("OK");
else puts("Sorry");
}
return 0;
}
2013题解:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
int sum = 1;
for(int i = 1; i < n; i ++)
{
sum = (sum + 1) * 2;
}
cout << sum << endl;
}
return 0;
}
2014题解:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
int mi = 100, mx = 0, sum = 0;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
mi = min(x, mi);
mx = max(x, mx);
sum += x;
}
printf("%.2lf\n", (double)(sum - mi - mx) / (n - 2));
}
return 0;
}
2015题解:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int n, m;
while(cin >> n >> m)
{
int sum = 0;
int x = 2;
vector<int> res;
for(int i = 1; i <= n; i ++)
{
sum += x;
x += 2;
if(i % m == 0)
{
res.push_back(sum / m);
sum = 0;
}
}
if(sum) res.push_back(sum / (n % m));
cout << res[0];
for(int i = 1; i < res.size(); i ++) cout << ' ' << res[i];
cout << endl;
}
return 0;
}
2016题解:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
if(!n) break;
vector<int> res;
int mi = 0x3f;
int j = 0;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
res.push_back(x);
if(x < mi)
{
mi = x;
j = i;
}
}
swap(res[0], res[j]);
cout << res[0];
for(int i = 1; i < n; i ++) cout << ' ' << res[i];
cout << endl;
}
return 0;
}
2017题解:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
while(n --)
{
string s;
cin >> s;
int cnt = 0;
for(int i = 0; i < s.size(); i ++)
{
if(s[i] >= '0' && s[i] <= '9') cnt ++;
}
cout << cnt << endl;
}
return 0;
}
2018题解:关键是找到第n年的牛的组成关系!
已知小母牛从第四年开始会生孩子
所以第n年的牛 = 第n - 3年的牛数量(这年的所有牛在第n年都会生一个孩子) + 去年的牛数量;
用递归找前面年份的牛数量即可;
#include <iostream>
#include <string>
using namespace std;
int calc(int x)
{
if(x == 1) return 1;
else if(x == 2) return 2;
else if(x == 3) return 3;
else return calc(x - 1) + calc(x - 3);//公式
}
int main()
{
int n;
while(cin >> n)
{
if(n == 0) break;
cout << calc(n) << endl;
}
return 0;
}
2019题解:上来直接排序复杂度高,已知有序找到相应位置插入即可;
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int N = 110;
int main()
{
int n, m;
while(cin >> n >> m)
{
if(!n && !m) break;
int i = 0;
bool s = false;
int a[N];
for(int i = 0; i < n; i ++) cin >> a[i];
for(i; i < n; i ++)
{
if(a[i] < m) cout << a[i] << ' ';
else
{
if(i == n) cout << m;
else cout << m << ' ';
s = true;
break;
}
}
if(i == n - 1 && !s) cout << m;
else if(i == n - 1 && s) cout << a[i];
else
{
while(i != n)
{
if(i == n - 1) cout << a[i];
else cout << a[i] << ' ';
i ++;
}
}
cout << endl;
}
return 0;
}
2020题解:
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
const int N = 110;
int main()
{
int n;
while(cin >> n)
{
unordered_map<int, int> h;
vector<int> a;
if(!n) break;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
h[abs(x)] = x;
a.push_back(abs(x));
}
sort(a.rbegin(), a.rend());
cout << h[a[0]];
for(int i = 1; i < n; i ++) cout << ' ' << h[a[i]];
cout << endl;
}
return 0;
}
2050题解:
首先我们要了解直线分割空间:每多增加一条直线,最多与n - 1条直线相交;每经过一个区域就会分割当前区域,则会有n 个区域被分割,又a0 = 1; a1 = 1 + 1, a2 = 1 + 1 + 2...可知
下面考虑折线情况:
其实折线可以看成有特定限制的两条直线;
在直线的基础上,每一条折线(有限制的直线)会比正常两条直线少分割两个区域(考虑折点处)
所以当有n条折线时,相当于在2n条直线所划分的区域基础上,减去 2n 个区域
即x条折线: x = 2 * x; (x + 1) * (x / 2) + 1 - x
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
while(n --)
{
int x;
cin >> x;
x = 2 * x;
cout << (x + 1) * (x / 2) + 1 - x << endl;
}
}
2051题解:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int x;
while(cin >> x)
{
vector<int> res;
while(x)
{
res.push_back(x % 2);
x /= 2;
}
for(int i = res.size() - 1; i >=0; i --) cout << res[i];
cout << endl;
}
return 0;
}
2052题解:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, m;
while(cin >> n >> m)
{
for(int i = 0; i < m + 2; i ++)
{
for(int j = 0; j < n + 2; j ++)
{
if((i == 0 || i == m + 1) && (j == 0 || j == n + 1)) cout << '+';
else if(i == 0 || i == m + 1) cout << '-';
else if(j == 0 || j == n + 1) cout << '|';
else cout << ' ';
}
cout << endl;
}
cout << endl;
}
return 0;
}
2053题解:
#include <iostream>
#include <vector>
using namespace std;
int change(int res)
{
if(res) return 0;
return 1;
}
int main()
{
int x;
while(cin >> x)
{
int res = 0;
for(int i = 1; i <= x; i ++)
{
if(i == 1) res = change(res);
else if(x % i == 0) res = change(res);
}
cout << res << endl;
}
return 0;
}
2054题解:坑很多:数字类型、数字范围等等
所以要用字符串进行读入,然后处理一下小数点后无用的0;
#include <iostream>
#include <string>
using namespace std;
string deal(string x)
{
int len = x.length();
if(x.find('.') != string::npos)
{
for(int i = len - 1; x[i] == '0'; i --)
len --;
x = x.substr(0, len);
if(x[len - 1] == '.') x = x.substr(0, len - 1);
}
return x;
}
int main()
{
string a, b;
while(cin >> a >> b)
{
a = deal(a);
b = deal(b);
if(a == b) puts("YES");
else puts("NO");
}
return 0;
}
2055题解:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin >> n;
while(n --)
{
char x;
int y;
cin >> x >> y;
if(x >= 'a' && x <= 'z') cout << y + -1 *(x - 'a' + 1) << endl;
else cout << y + (x - 'A' + 1) << endl;
}
}
2056题解:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
double x[10], y[10];
while(cin >> x[1] >> y[1] >> x[2] >> y[2] >> x[3] >> y[3] >> x[4] >> y[4])
{
sort(x + 1, x + 5);
sort(y + 1, y + 5);
printf("%.2lf\n", (x[3] - x[2]) * (y[3] - y[2]));
}
return 0;
}
2057题解:
解法一:自己写的进制转换:第一次没有AC,想了一下因为和可能会超出int范围 改为long long类型存储;
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
typedef long long LL;
using namespace std;
int number(int x)
{
if(x >= 'A' && x <= 'Z') return x - 'A' + 10;
else return x - '0';
}
string get_number(int x)
{
string res;
if(x >= 0 && x <= 9) res = x + '0';
else res = 'A' + (x - 10);
return res;
}
LL change(string x)//秦九韶算法
{
LL res = 0;
for(int i = 0; i < x.size(); i ++)
{
res = res * 16 + number(x[i]);
}
return res;
}
void calc(LL x)
{
bool st = false;
if(x < 0) st = true, x = abs(x);
vector<LL> res;
while(x)
{
res.push_back(x % 16) ;
x /= 16;
}
reverse(res.begin(), res.end());
if(st) cout << '-';
for(auto c : res) cout << get_number(c);
cout << endl;
}
int main()//16进制
{
string a, b;
while(cin >> a >> b)
{
LL res;
int tag_a, tag_b;
if(a[0] == '-') tag_a = 1, a = a.substr(1, a.size() - 1);
else if(a[0] == '+') tag_a = 0, a = a.substr(1, a.size() - 1);
else tag_a = 0;
if(b[0] == '-') tag_b = 1, b = b.substr(1, b.size() - 1);
else if(b[0] == '+') tag_b = 0, b = b.substr(1, b.size() - 1);
else tag_b = 0;
if(tag_a && tag_b) res = -(change(a) + change(b));
else if(!tag_a && !tag_b) res = change(a) + change(b);
else if(!tag_a && tag_b) res = change(a) - change(b);
else res = change(b) - change(a);
if(res == 0) cout << '0' << endl;
else calc(res);
}
return 0;
}
解法二:用c++的关键字(方便)
ps:
1. hex表示之后的数字以16进制方式输出
oct表示之后的数字以8进制方式输出
dec表示之后的数字以10进制方式输出
2.setiosflags(ios::uppercase) 16进制数大写输出
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
long long A,B;
while(cin>>hex>>A>>B)
{
long long sum;
sum=A+B;
if(sum>=0)
cout<<setiosflags(ios::uppercase)<<hex<<sum<<endl;
else
{ long long asum=abs(sum);
cout<<"-";
cout<<setiosflags(ios::uppercase)<<hex<<asum<<endl;
}
}
}
2058题解:
穷举左右端点时间复杂度太高;所以利用求和公式 只需要一次遍历
Sn = n * a1 + n ^(n - 1) / 2 * d; 所以只需要枚举区间长度 判断是否满足上述表达式即可;
//求子序列(连续)和 == M 并且输出序列;
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int n, m;
while(cin >> n >> m)
{
if(!n && !m) break;
int maxlen = sqrt(m * 2);
for(int i = maxlen ;i > 0; i --)
{
int t = m - i *(i - 1) / 2;
if(t % i == 0) printf("[%d,%d]\n", t / i, t / i + i - 1);
}
cout << endl;
}
}
2059题解:DP问题(多练)
DP问题:状态表示:f[i] 表示到第i个加油站的最短时间;
状态表示方程:f[i] = 最小值:从j处加满油 到 i 点的时间 + 到 j 点的最短时间;
遍历j点 找出最优解即可;
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 110, INF = 100000010;
double f[N], d[N];
double l, c ,t, vr, vt1, vt2;
int n;
int main()
{
while(cin >> l >> n >> c >> t >> vr >> vt1 >> vt2)
{
for(int i = 1; i <= n; i ++) cin >> d[i];
d[n + 1] = l;
for(int i = 1; i <= n + 1; i ++)
{
f[i] = INF;
for(int j = 0; j < i; j ++)
{
double Time;
if(d[i] - d[j] <= c) Time = (d[i] - d[j]) / vt1;
else Time = c / vt1 + (d[i] - d[j] - c) / vt2;
Time += f[j];
if(j > 0) Time += t;
f[i] = min(f[i], Time);
}
}
if(f[n + 1] < (l / vr)) puts("What a pity rabbit!");
else puts("Good job,rabbit!");
}
}
2060题解:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
int main()
{
cin >> n;
while(n --)
{
int b, p, o;
cin >> b >> p >> o;
if(b > 6) p += (b - 6) * 8 + 27;
else p += 7 * b - (b * (b - 1) / 2);
if(p >= o) puts("Yes");
else puts("No");
}
return 0;
}
2061题解:本身问题很简单,但是要小心数据类型;
第一次用int 型 TLE:发现数据有可能为浮点数,改为double 后AC;(没说数据类型的都用double!)
#include <iostream>
#include <string>
using namespace std;
int n;
int main()
{
cin >> n;
while(n --)
{
int k;
double a = 0, b = 0;
scanf("%d", &k);
bool success = true;
while(k --)
{
char name[35];
double c, s;
scanf("%s%lf%lf", name, &c, &s);
if(s >= 0 && s < 60) success = false;
else a += c * s, b += c;
}
if(!success) printf("Sorry!\n");
else printf("%.2lf\n",a / b);
if(n!=0) printf("\n");
}
return 0;
}
2062题解:
第一次WA:又是数据类型!!20个数组的集合数量为6613313319248080000 超出int型了 所以要用long long存储!
思想:一组一组的找,每找到一组,将当前数字去掉,m变为n - 1个数中的集合下标,直到找完或者m == 0为止;
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 30;
LL c[N];
int main()
{
LL n, m;
c[1] = 1;
for(int i = 2; i <= N; i ++) c[i] = i * (c[i - 1] + 1);//统计i个数的集合数量
while(cin >> n >> m)
{
vector<int> a;
bool is_first = true;
for(int i = 1; i <= n; i ++) a.push_back(i);
while(m && n)
{
LL x = (m - 1) / (c[n - 1] + 1);//表示属于第几组
if(is_first)//输出
{
cout << a[x];
is_first = false;
}
else cout << ' ' << a[x];
a.erase(a.begin() + x);//去掉该数
m = (m - 1) % (c[n - 1] + 1);//m变为下一轮要求的第m个集合
n --;
}
cout << endl;
}
return 0;
}
2063题解:
二分图匹配问题:匈牙利算法
匈牙利算法的核心是寻找増广路,是一种用增广路径求二分图最大匹配的算法。如果找不到増广路了,说明已经达到最大匹配。
总结就是两句:先到先得(匹配上了就先记录下来),能让就让(如果被别人匹配走了,看看那个女生可不可以选别人,如果可以她就让给你--find一下看看能不能找别人--此时匹配过的男生就不看了 所以每次一个女生选人时要标记一下)
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N = 1010;
int n, m, k;
int map[N][N];//关系
int vis[N];//是否询问过
int match[N];//男i的匹配对象;
int find(int x)
{
for(int i = 1; i <= n; i ++)//匹配男生
{
if(vis[i] == 0 && map[x][i])
{
vis[i] = 1;
if(match[i] == -1 || find(match[i]))//男生未被选择(先到先得) or 被选了但是女二可以找到其他对象(让给她!)
{
match[i] = x;
return 1;
}
}
}
return 0;
}
int main()
{
while( cin >> k)
{
if(k == 0) break;
cin >> m >> n;
memset (map, 0, sizeof map);
memset (match, -1, sizeof match);
while(k --)
{
int a, b;
cin >> a >> b;
map[a][b] = 1;
}
int res = 0;
for(int i = 1; i <= m; i ++)
{
memset(vis, 0, sizeof vis);//每次选择个
if(find(i)) res ++;
}
cout << res << endl;
}
return 0;
}
2064题解:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
int n;
LL calc(int x)
{
if(x == 1) return 2;
else return 3 * calc(x - 1) + 2;
}
int main()
{
while(cin >> n)
{
cout << calc(n) << endl;
}
return 0;
}
2065题解:先找规律,发现是快速幂问题;
快速幂:等价替换:判断一下奇偶,然后底数一次次的算平方
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
typedef long long LL;
int n;
int calc(LL x, LL m)//等价替换:判断一下奇偶,然后底数一次次的算平方
{
int res = 1;
while(m)
{
if(m % 2 == 1)//m为奇数时提出一个x最后再乘进去,最后到1时乘上res(1或者x 取决于m最初是否为奇数)
{
res = (res * x) % 100;
}
m >>= 1;//m = m / 2
x = (x * x) % 100;//相当于指数拿出个2让底数变为平方
}
return res;
}
int main()
{
while(cin >> n)
{
if(!n) break;
for(int i = 1; i <= n; i ++)
{
LL x;
cin >> x;
int res = calc(4, x - 1) + calc(2, x - 1);
cout << "Case "<< i << ": ";
cout << res % 100 << endl;
}
cout << endl;
}
return 0;
}
2066题解:dijkstra问题
小心 a 到 b 可能有多条路径(取最小的即可)
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, T, S, D;
int g[N][N];
int dist[N];
bool st[N];
void dijkstra(int s)
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[s] = 0;
for(int i = 0; i < n; i ++)
{
int t = -1;
for(int j = 1; j <= n; j ++)
{
if(!st[j] && (t == -1 || dist[j] < dist[t]))
t = j;
}
st[t] = true;
for(int j = 1; j <= n; j ++)
if(dist[j] > dist[t] + g[t][j])
dist[j] = dist[t] + g[t][j];
}
}
int main()
{
while(cin >> T >> S >> D)
{
n = 0;
memset(g, 0x3f, sizeof g);
while(T --)
{
int a, b, w;
cin >> a >> b >> w;
g[a][b] = g[b][a] = min(g[a][b], w);
n = max(a, n);
n = max(b, n);
}
vector<int> h_city;
while(S --)
{
int x;
cin >> x;
h_city.push_back(x);
}
vector<int> d_city;
while(D --)
{
int x;
cin >> x;
d_city.push_back(x);
}
int res = 100000;
for(auto c : h_city)
{
dijkstra(c);
for(auto item : d_city)
{
res = min(res, dist[item]);
}
}
cout << res << endl;
}
return 0;
}
2067题解:(数学问题)卡特兰数!
1,1,2,5,14,42,132,429......
#include <cstdio>
using namespace std;
int main()
{
long long Catalan[40] = {0};
Catalan[0] = 1;
Catalan[1] = 1;
for (int i = 2 ; i <= 35 ; i++)
for (int j = 0 ; j <= i - 1 ; j++)
Catalan[i] += Catalan[j] * Catalan[i - 1 - j];
int num = 1;
int n;
while (~scanf ("%d",&n) && n != -1)
printf ("%d %d %lld\n",num++,n,Catalan[n] * 2);
return 0;
}
2068题解:数学问题,找排序规律
保证一半及以上正确,找剩下的位置错排的方案
#include <iostream>
using namespace std;
const int N = 26;
int d[N];
long long C(int a, int b)
{
long long x = 1, y = 1;
for(int i = 1; i <= b; i ++) y *= i;
for(int i = 0; i < b; i ++)
{
x *= a --;
}
int res = x / y;
return res;
}
int main()
{
int n;
d[1] = 0, d[2] = 1;
for(int i = 3; i <= 12; i ++) d[i] = (i - 1) * (d[i - 1] + d[i - 2]);
while(cin >> n)
{
if(!n) break;
long long cnt = 1;
for(int i = 1; i <= n / 2; i ++)//遍历错排的个数求总和
{
cnt += C(n, i) * d[i];//选择的人数 * 错排的方案数
}
cout << cnt << endl;
}
}
2069题解:
有限制的完全背包问题;
没限制硬币个数的话很简单,就是单纯的完全背包问题;
但是限制硬币个数 <= 100;一开始想用双状态表示,
f[i][j]表示使用前i种硬币(5种)下总和为j的方案数,但是要记录每个方案使用的硬币个数非常复杂。不可取
则考虑换一种状态表示:计算使用前i个硬币(100个)下总和达到j的方案数量;
最后从1 - 100遍历求总的方案数即可;
//完全背包问题
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int N = 260;
long long f[N][N];//用100个硬币下总和为j的方案
int w[6] = {0, 1, 5, 10, 25, 50};
int s[N][N];//记录总硬币个数
int main()
{
int n;
memset(f, 0, sizeof f);
f[0][0] = 1;
for(int i = 1; i <= 5; i ++)//对每个物品用100次,求方案
for(int j = 1; j <= 100; j ++)
for(int k = w[i]; k <= 251; k ++)
f[j][k] += f[j - 1][k - w[i]];
while(cin >> n)
{
long long res = 0;
for(int i = 0; i <= 100; i ++) res += f[i][n];
cout << res << endl;
}
return 0;
}
2070题解:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int N = 51;
long long a[N];
int main()
{
int n;
a[0] = 0, a[1] = 1;
for(int i = 2; i <= N; i ++) a[i] = a[i - 1] + a[i - 2];
while(cin >> n)
{
if(n == -1) break;
cout << a[n] << endl;
}
return 0;
}
2071题解:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 51;
long long a[N];
int main()
{
int n;
cin >> n;
while(n --)
{
int k;
cin >> k;
double mx = 0;
while(k --)
{
double x;
cin >> x;
mx = max(x, mx);
}
printf("%.2lf\n", mx);
}
return 0;
}
2072题解:
用stringstream进行二次读入⭐ 头文件<sstream>
map记录出现过的单词
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
using namespace std;
int main()
{
string line;
while(getline(cin, line))
{
if(line == "#") break;
unordered_map<string, int> words;
stringstream sinn(line);
string word;
while(sinn >> word)
{
words[word] ++;
}
cout << words.size() << endl;
}
return 0;
}
2073题解:
前缀和思想:两点求差 == 各自到原点的距离之差;
到原点:找有规律的点存储下来,在基础上进行计算
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 200;
double d[N];
double find(int a, int b)
{
double res;
res = d[a + b] - b * sqrt(2);
return res;
}
int main()
{
int n;
cin >> n;
d[1] = 1 + sqrt(2);
for(int i = 2; i <= N; i ++) d[i] = d[i - 1] + i * sqrt(2) + sqrt((i - 1) * (i - 1) + i * i);
while(n --)
{
int x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
double res = abs(find(x1, y1) - find(x2, y2));
printf("%.3lf\n", res);
}
return 0;
}
2074题解:
要特判一个字符的时候
并且注意之间的空行
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n, count = 0;
char a, b;
while(cin >> n >> a >> b)
{
if(count != 0) printf("\n"); //踩坑点2
count = 1;
if(n == 1)
{
printf("%c\n", a);
continue;
}
string f[81][81];
if(n / 2 % 2 == 0) swap(a, b);
int m = n;
for(int i = 0, j = 0; i < n / 2 || j < n / 2; i ++, j ++)
{
for(int k = j; k < m; k ++) f[i][k] = b;
for(int k = i; k < m; k ++) f[k][j] = b;
swap(a, b);
m --;
}
m = 0;
if(n / 2 % 2 == 0) swap(a, b);
for(int i = n - 1, j = n - 1; i > 0 || j > 0; i --, j --)
{
for(int k = j; k >= m; k --) f[i][k] = a;
for(int k = i; k >= m; k --) f[k][j] = a;
swap(a, b);
m ++;
}
f[0][0] = " ", f[0][n - 1] = " ", f[n - 1][0] = " ", f[n - 1][n - 1] = " ";
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
cout << f[i][j];
}
cout << endl;
}
}
return 0;
}
2075题解:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n;
cin >> n;
while(n --)
{
int a, b;
cin >> a >> b;
if(a % b == 0) puts("YES");
else puts("NO");
}
return 0;
}
2076题解:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
while(n --)//求各自度数之差
{
double h, m, s;
cin >> h >> m >> s;
if(h > 12) h -= 12;
double m_d = 6 * m+ 0.1 * s;
double h_d = 30 * h + 0.5 * (m + s / 60);
if(h_d < m_d) swap(h_d, m_d);
if((h_d - m_d) > 180)
{
int res = 360 - h_d + m_d;
cout << res << endl;
}
else
{
int res = h_d - m_d;
cout << res << endl;
}
}
return 0;
}
2077题解:
#include <iostream>
using namespace std;
int han(int x)
{
if(x == 1) return 1;
else return 3 * han(x - 1) + 1;
}
int main()
{
int n;
cin >> n;
while(n --)//求各自度数之差
{
int x;
cin >> x;
int res;
if(x == 1) res = 2;
else res = 2 * han(x - 1) + 2;
cout << res << endl;
}
return 0;
}
2078题解:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 50;
int main()
{
int T;
cin >> T;
while(T --)
{
int n, m;
cin >> n >> m;
int w[N];
int mi = 110;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
mi = min(x, mi);
}
cout << (100 - mi) * (100 - mi) << endl;
}
return 0;
}
2079题解:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 50;
int f[9][N];
int w[N], cnt[N];
int main()
{
int T;
cin >> T;
while(T --)
{
memset(f, 0, sizeof f);
int n, k;
cin >> n >> k;
for(int i = 1; i <= k; i ++)
{
cin >> w[i] >> cnt[i];
}
f[0][0] = 1;
for(int i = 1; i <= k; i ++)
for(int j = 0; j <= n; j ++)
for(int s = 0; s * w[i] <= j && s <= cnt[i]; s ++)
f[i][j] += f[i - 1][j - s * w[i]];
cout << f[k][n] << endl;
}
return 0;
}
2080题解:
数量积公式求cos再用acos转化为角度
acos():返回弧度数(参数-1 到 1)的反余弦值,
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#define PI acos(-1.0)//求180°的弧长 = 3.1415926535
using namespace std;
int main()
{
int T;
cin >> T;
while(T --)
{
double x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
//输出结果为弧度,弧度转化为角度 弧长 / PI * 180;
printf("%.2lf\n", acos((x1 * x2 + y1 * y2) / (sqrt(x1 * x1 + y1 *y1) * sqrt(x2 * x2 + y2 * y2))) * 180 / PI);
}
return 0;
}
2081题解:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main()
{
int T;
cin >> T;
while(T --)
{
string s, res;
cin >> s;
for(int i = s.size() - 1; i > s.size() - 6; i --)
{
res = s[i] + res;
}
cout <<'6' << res << endl;
}
return 0;
}
2082题解:
完全背包问题:求<=50的方案数
状态表示:考虑前i个数价值达到50的方案数;
则答案 = 考虑前i个数 价值从 1 - 50的方案数总和。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N = 27, M = 51;
int cnt[N], f[N][M];
int main()
{
int T;
cin >> T;
while(T --)
{
for(int i = 1; i < N ; i ++) cin >> cnt[i];
memset(f, 0, sizeof f);
f[0][0] = 1;
for(int i = 1; i < N; i ++)
for(int j = 0; j <= 50; j ++)
for(int k = 0; k <= cnt[i] && k * i <= j; k ++)
{
f[i][j] += f[i - 1][j - k * i];
}
int res = 0;
for(int j = 1; j <= 50; j ++) res += f[26][j];
cout << res << endl;
}
return 0;
}
一维数组优化版本:
我们只需要考虑上一轮决策的状态,可以用一维数组从大到小更新(用到的状态体积一定是小于等于当前体积 j 的)要注意特判一下:不选当前单词时方案数应该直接等于上一个状态的方案数(想了很久才发现这个点)
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N = 27, M = 51;
int f[M];
int main()
{
int T;
cin >> T;
while(T --)
{
memset(f, 0, sizeof f);
f[0] = 1;
for(int i = 1; i < N; i ++)
{
int cnt;
cin >> cnt;
for(int j = 50; j >= 1; j --)
for(int k = 0; k <= cnt && k * i <= j; k ++)
{
if(k != 0) f[j] += f[j - k * i];//要考虑不选当前单词的时候,此时方案数不是相加而是相等;
}
}
int res = 0;
for(int j = 1; j <= 50; j ++) res += f[j];
cout << res << endl;
}
return 0;
}
2083题解:(未跑)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510;
int d[N];
int main()
{
int T;
cin >> T;
while(T --)
{
int n;
cin >> n;
for(int i = 0; i < n; i ++) cin >> d[i];
sort(d, d + n);
int start = d[n / 2];
int res = 0;
for(int i = 0; i < n; i ++) res += abs(d[i] - start);
cout << res << endl;
}
return 0;
}
2084题解:
一、dfs解法:超时(意料之中)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 110;
int res;
vector<int> h[N];
void dfs(int x, int sum, int end, int pre)
{
if(x == end)
res = max(res, sum);
else
{
for(int i = pre; i <= pre + 1; i ++)
dfs(x + 1, sum + h[x][i], end, i);
}
}
int main()
{
int T;
cin >> T;
while(T --)
{
for(int i = 0; i < N; i ++) h[i].clear();
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
int j = i;
while(j --)
{
int x;
cin >> x;
h[i].push_back(x);
}
}
res = 0;
dfs(1, 0, n + 1, 0);
cout << res << endl;
}
return 0;
}
二、DP解法
状态表示:从顶层到前i层第j个数的最大权值和;(每一层的最大值都是基于上一层每个点最大值进行决策(且最多就两种选择));
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 110;
int dp[N][N];
int main()
{
int T;
cin >> T;
while(T --)
{
int n;
cin >> n;//层数
for(int i = 1; i <= n; i ++)
for(int j = 0; j < i; j ++)
{
int x;
cin >> x;
if(j == 0) dp[i][j] = dp[i - 1][j] + x;
else if(j == i - 1) dp[i][j] = dp[i - 1][j - 1] + x;
else dp[i][j] = max(dp[i - 1][j - 1] + x, dp[i - 1][j] + x);
}
int res = 0;
for(int i = 0; i < n; i ++) res = max(res, dp[n][i]);
cout << res << endl;
}
return 0;
}
2085题解:简单递归问题
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
void calc(int n, long long h, long long l)
{
if(!n) cout << h << ", " << l << endl;
else
{
calc(n - 1,h * 3 + l * 2, h + l);
}
}
int main()
{
int n;
while(cin >> n)
{
if(n == -1) break;
calc(n, 1, 0);
}
return 0;
}
2086题解:数学问题、找规律
A(n+1) = (n + 1)A1 - n * A0 + 2 * i C[n - i];(c从0 开始)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3010;
double c[N];
int main()
{
int n;
while(cin >> n)
{
double a, an1;
cin >> a >> an1;
for(int i = 0; i < n; i ++) cin >> c[i];
double a1 = an1 + n * a;
for(int i = 1; i <= n; i ++) a1 -= 2 * i * c[n - i];
printf("%.2lf\n", a1 / (n + 1));
}
return 0;
}
2087题解:字符串匹配问题;(水)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3010;
double c[N];
int main()
{
string s, d;
while(cin >> s)
{
if(s == "#") break;
else
{
cin >> d;
int len = d.size();
int cnt = 0;
for(int i = 0; i < s.size(); i ++)
{
string z = s.substr(i, len);
if(z == d)
{
cnt ++;
i += len - 1;
}
}
cout << cnt << endl;
}
}
return 0;
}
2088题解:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 51;
int a[N];
bool is_first = true;
int main()
{
int n;
while(cin >> n)
{
if(!n) break;
else
{
if(!is_first) cout << endl;
is_first = false;
int sum = 0;
for(int i = 0; i < n; i ++)
{
cin >> a[i];
sum += a[i];
}
int d = sum / n, res = 0;
for(int i = 0; i < n; i ++) res += max(0, a[i] - d);
cout << res << endl;
}
}
return 0;
}
2089题解:一次找完10^6次方,用字符串匹配来找(strstr函数,但是注意参数为char型)
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int N = 1e6 + 10;
int r[N];
int main()
{
for(int i = 1; i <= N; i ++)
{
string cc = to_string(i);
char s[10];
for(int i = 0; i < cc.size(); i ++) s[i] = cc[i];
if(strstr(s, "4") != NULL || strstr(s, "62") != NULL) r[i] = 0;
else r[i] = 1;
}
int a, b;
while(cin >> a >> b)
{
if(!a && !b) break;
else
{
int sum = 0;
for(int i = a; i <= b; i ++)
{
sum += r[i];
}
cout << sum << endl;
}
}
return 0;
}
2090题解:(水题)
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int N = 1e6 + 10;
int r[N];
int main()
{
string s;
double cnt, price, sum = 0;
while(cin >> s >> cnt >> price)
{
sum += cnt * price;
}
printf("%.1lf\n", sum);
return 0;
}
2091题解:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main()
{
string s;
int n;
bool is_first = true;
while(cin >> s)
{
if(s == "@") break;
else
{
if(!is_first) cout << endl;
is_first = false;
cin >> n;
for(int i = 0; i < n; i ++)
{
for(int j = 0; j <= n - 1 + i; j ++)
{
if(i + 1 == n) cout << s;
else
{
if(j == n - 1 - i || j == n - 1 + i) cout << s;
else cout << " ";
}
}
cout << endl;
}
}
}
return 0;
}
2093题解:排序题 + 对输出的处理
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Info{
string name;
int ac, ti;
bool operator< (const Info &t) const{
if(ac != t.ac) return ac > t.ac;
else if(ti != t.ti) return ti < t.ti;
else return name < t.name;
}
};
vector<Info> students;
int main()
{
int n, m;
cin >> n >> m;
int ac_si = 0, ti_si = 0;
string name;
while(cin >> name)
{
int ac = 0, ti = 0;
for(int i = 0;i < n; i ++)
{
string x;
cin >> x;
if(x[0] != '-' && x[0] != '0')
{
ac ++;
int d = x.find('(');
ti += stoi(x);
if(d != -1) ti += stoi(x.substr(d + 1, x.size() - d - 2)) * m;
}
}
ac_si = max(ac, ac_si);
ti_si = max(ti, ti_si);
students.push_back({name, ac, ti});
}
sort(students.begin(), students.end());
for(auto c : students)
{
int i = 10 - c.name.size();
cout << c.name;
while(i --) cout << ' ';
i = 2 - to_string(c.ac).size() + 1;
while(i --) cout << ' ';
cout << c.ac;
i = 4 - to_string(c.ti).size() + 1;
while(i --) cout << ' ';
cout << c.ti;
cout << endl;
}
return 0;
}
2094题解:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
int n, i, j;
string win[999], lose[999], temp;
bool mark[999];
while (scanf("%d", &n)) {
if (!n) {
break;
}
// 初始化标记数组
memset(mark, 1, sizeof(mark));
for (i = 0; i < n; i++) {
cin >> win[i] >> lose[i];
}
// 标记处“无效比赛”
for (i = 0; i < n; i++) {//j输过则它的比赛无效
for (j = 0; j < n; j++) {
if (win[j] == lose[i] && mark[j]) {
mark[j] = false;
}
}
}
// 找出第一个“有效比赛”中的赢者
for (i = 0; !mark[i]; i++) { }
temp = win[i];
// 判断是否所有的赢者都是一个人
for (j = i + 1; j < n; j++) {
if (mark[j] && win[j] != temp) {
break;
}
}
if (j != n) {
printf("No\n");
}
else {
printf("Yes\n");
}
}
return 0;
}