今天开的是 2017-united-kingdom-ireland-programming-contest-ukiepc-2017
模拟和贪心居多,被一个题卡了好久
真的很菜了
A - Alien Sunset
日落与日出
暴力枚举,数字很小
记得取模
要求在每个地方都能看烟花,所以都要在晚上才行
大于等于注意一下 ok
//2020.4
//a
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e6 + 5, inf = 0x3f3f3f;
int N;
struct P {
int h,l, r;
}p[66];
// h h <= 100
int hh, maxh,ans;
bool f = 0;
bool okk(int i,int id) {
i = i % p[id].h;
if (p[id].r >= p[id].l) {
return (i >= p[id].r || i <= p[id].l);
}
return (i >= p[id].r && i <= p[id].l);
}
int main() {
cin >> N;
for (int i = 1;i <= N;i++) {
cin >>p[i].h>> p[i].l >> p[i].r;
hh = max(hh, p[i].h);
}
maxh = 1825 * hh;
for (int i = 0;i < maxh;i++){
bool ok = 1;
for (int j = 1;j <= N;j++) {
//if (i == 6 && okk(i, j))
//cout << "GG"<<j << endl;
if (!okk(i,j)) {
ok = 0;
break;
}
}
if (ok) {
//cout << i << "OK" << endl;
f = 1;
ans = i;
break;
}
}
if (!f) cout << "impossible" << endl;
else cout << ans << endl;
return 0;
}
B - Breaking Biscuits
我觉得这不算计算几何吧。。
枚举 这都能,果然是 欢乐场啊hhh
但是了解了一下旋转卡(qia)壳,还是很不错的哈
旋转卡壳可以用来求随机点对的最大距离,可以使用凸包,利用三角形面积的先上升、后下降的特点(也就是凸包的特点啦),达到O(n)的时间复杂度。
算法如其名,是用2根线夹着多边形,可以求多边形的最大直径(?是这么讲吗,总之就是多边形内距离最大的两个点吧)
这里也可,用来求多边形的最小距离(??
但是用点到直线暴力求解、不加优化都能过,水水水水水
//2020.4
//b
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 405,inf=0x3f3f3f3f;
const double err = 1e-9;
struct Points {
int x, y;
Points(int x = 0, int y = 0) :x(x), y(y) {}
};
typedef Points Vector;
Vector operator -(Points A, Points B) {
return Vector(A.x - B.x, A.y - B.y);
}
int n, m;
Points p[maxn], ch[maxn];
int Cross(Vector A, Vector B) {
return A.x*B.y - A.y*B.x;
}
bool cmp(Points a, Points b) {
bool ret = false;
if (a.x < b.x || (a.x == b.x&&a.y < b.y)) ret = true;
return ret;
}
void ConvexHull() {
sort(p, p + n, cmp);
m = 0;
for (int i = 0;i < n;++i) {
while (m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m--;
ch[m++] = p[i];
}
int k = m;
for (int i = n - 2;i >= 0;--i) {
while (m > k&&Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m--;
ch[m++] = p[i];
}
if (n > 1) m--;
}
int dis(Points a, Points b) {
return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}
/*
int maxdis = 0;
void rotating_caliper() {
if (n == 3) {
maxdis = max(dis(p[0], p[1]), dis(p[0], p[2]));
maxdis = max(maxdis, dis(p[1], p[2]));
}
else {
int j = 2;
for (int i = 0;i < m;++i) {
cout << ch[i].x << ", " << ch[i].y << endl;
while (abs(Cross(ch[i] - ch[i + 1], ch[j] - ch[i + 1])) < abs(Cross(ch[i] - ch[i + 1], ch[j + 1] - ch[i + 1]))) {
j = (j + 1) % m;
}
maxdis = max(maxdis, dis(ch[i], ch[j]));
}
}
}*/
double ans = inf;
double dis(Points P, Points A, Points B) {
if (A.x == B.x) return abs(P.x - A.x);
double res = ((A.y-B.y)*P.x + (B.x-A.x)*P.y + A.x*B.y - B.x*A.y)/(1.0 *sqrt(dis(A, B)));
return res;
}
void cal() {
for (int i = 0;i < m;i++) {
double maxtmp = 0;
for (int j = 0;j < m;j++) {
if (j == i || j == (i + 1)%m) continue;
//cout << ch[j].x << "," << ch[j].y << " to " << ch[i].x << "," << ch[i].y << " & " << ch[(i + 1)%m].x << "," << ch[(i + 1)%m].y << endl;
double tmp = dis(ch[j], ch[i], ch[(i + 1)%m]);
if (tmp > maxtmp) maxtmp = tmp;
}
//cout << maxtmp << endl;
ans = min(ans, maxtmp);
}
}
int main() {
cin >> n;
for (int i = 0;i < n;++i)
cin >> p[i].x >> p[i].y;
ConvexHull();
//rotating_caliper();
cal();
cout << fixed << setprecision(8)<<ans << endl;
return 0;
}
C - Cued In
学会了斯诺克。。。。。。。。。
正常情况下,每个红球为1分,各种彩zd球分值从2至7分,黄球2分,绿球3分,咖啡球4分,蓝球5分,粉球6分,黑球7分。
击球必须遵循“一红一彩”的顺序。
因为可以循环使用,我们的第一轮得分首先是把所有球发分值*个数
cnt【i】 x mp【i】
然后循环使用分值最高的球, 一红一彩
所以答案再加cnt[1] x mp[]max
最后再+红球(如果场上只剩红球,则不能继续了
所以当都是红球的时候,就只能拿一分。(还是讲不清
//2020.4
//c
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e6 + 5, inf = 0x3f3f3f;
int N,ans=0;
string s[50];
int cnt[50];
map<string, int> mp;
int main() {
cin >> N;
mp["red"] = 1;
mp["yellow"] = 2;
mp["green"] = 3;
mp["brown"] = 4;
mp["blue"] = 5;
mp["pink"] = 6;
mp["black"] = 7;
for (int i = 1;i <= N;i++) {
cin >> s[i];
cnt[mp[s[i]]]++;
}
int ans = 0;
if (cnt[1] == N) {
ans = 1;
}
else {
for (int k = 2;k <= 7;k++) {
ans += k * cnt[k];
}
if (cnt[1]) {
int num = 0;
for (int k = 7;k >= 1;k--) {
if (cnt[k]) {
num = k;
break;
}
}
// cout << num << " " << cnt[1] << endl;
ans += cnt[1] * num;
}
ans += cnt[1];
}
cout << ans << endl;
return 0;
}
D - Deranging Hat
反向模拟,把排序后的字符数组恢复成原来的数组。
在目标数组taget中找交换的位置,按照要求A《B,就交换。
由于这里AB位置可以对调,实际上可以任意交换
1.a<b, a在b前,那就a b
2. a>=b,a在b前,那就b a
//2020.4
//d
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e6 + 5, inf = 0x3f3f3f;
char s[1005],target[1005];
int main() {
cin >> s;
for (int i = 0;i < strlen(s);i++) {
target[i] = s[i];
}
sort(target, target + strlen(target));
for (int i = 0;i < strlen(target);i++) {
if(target[i]!=s[i]){
char find = s[i];
//cout << find << endl;
//cout << i << endl;
for (int j = i + 1;j < strlen(s);j++) {
if (target[j] == find) {
if(target[i])
//t[j] > t[i]
//cout << target[j] << " ?? " << target[i] << endl;
if(target[j]>=target[i])
cout << j + 1 << " " << i + 1 << endl;
else cout << i + 1<< " " << j + 1 << endl;
swap(target[i], target[j]);
break;
}
//cout << t << endl;
}
}
}
return 0;
}
E - Education
贪心
按价格排序后从小到大,对应每一个专业,找能满足他们要求的房子中价格最低的,并做标记,记录答案。
因为要实现价格最小,所以按价格排序
//2020.4
//e
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 5e3 + 5, inf = 0x3f3f3f;
struct P {
int p, r,id;
bool operator <(const P & a) {
return r < a.r;
}
}b[maxn];
struct D {
int id, num;
bool ok;
bool operator<(D & d) {
return num < d.num;
}
}s[maxn];
bool used[maxn];
int n, m,ans[maxn],cnt;
int main() {
cin >> n >> m;
for (int i = 1;i <= n;i++) { cin >> s[i].num; s[i].id = i; }
for (int i = 1;i <= m;i++) cin >> b[i].p;
for (int i = 1;i <= m;i++) { cin >> b[i].r; b[i].id = i; }
sort(b + 1, b + 1 + m);
for (int j = 1;j <= m;j++) {
int bigg = 0, pos = 0,posb=0;
for (int i = 1;i <= n;i++) {
if (!s[i].ok && !used[b[j].id] && s[i].num <= b[j].p ) {
if (bigg < s[i].num) {
bigg = s[i].num;
pos = i;
posb = j;
}
}
}
if (pos) {
ans[pos] = b[posb].id;
used[b[posb].id] = 1;
s[pos].ok = 1;
cnt++;
}
}
if (cnt < n)cout << "impossible" << endl;
else {
for (int i = 1;i < n;i++)
cout << ans[i] << " ";
cout << ans[n] << endl;
}
return 0;
}
F - Flipping Coins
看数据范围和题目,求期望-找规律推公式 or dp
选择dp
dp[i][j]表示投掷i次硬币后有j个朝上
状态转移:在没有投满之前 j<n,朝上的个数都是只增不减的
若开出了新的正面,j+1;若没有开出,翻回原来的样子,j不变;
而若j=n,dp[i][n-1]的状态由三种情况推来:
1.dp[i-1][j-1] hit
2.dp[i-1][j] unhit (1&2 都是0.5概率)
3.dp[i-1][n] unhit
这时候个数不可能再增加,反而可能减少,所以要特别讨论。
最后:
dp[i][j]+=dp[i-1][j-1]*0.5 (j>=1) (hit)
dp[i][j]+=dp[i-1][j]*0.5(unhit)
dp[i][n-1]+=dp[i-1][n]*0.5
#include"pch.h"
//2020.4
//f
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 405;
int n,k;
double dp[maxn][maxn];
int main() {
cin >> n>>k;
dp[0][0] = 1.0;
//dp[i][j]抛第i个硬币后,j个硬币朝上的概率
for (int i = 1;i <= k;i++) {
for (int j = 0;j <= n;j++) {
//翻回去了
dp[i][j] += dp[i - 1][j] * 0.5;
//翻出来一个新的
if (j >= 1) dp[i][j] += dp[i - 1][j - 1] * 0.5;
//翻少了
}
dp[i][n - 1] += dp[i - 1][n] * 0.5;
}
double ans = 0;
//求期望
for (int i = 1;i <= n;i++)
ans += dp[k][i] * i;
cout <<fixed<<setprecision(7)<<ans << endl;
return 0;
}
I - I Work All Day
题意:求余料最少,
枚举,取模即可
//2020.4
//i
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e6 + 5, inf = 0x3f3f3f;
int N,h[maxn],H;
int main() {
cin >> N;
int id=0,ans=inf;
for (int i = 1;i <= N;i++) {
cin >> h[i];
}
cin >> H;
for (int i = 1;i <= N;i++) {
int tmp = H % h[i];
if (tmp < ans) {
ans = tmp;
id = i;
}
}
cout << h[id] << endl;
return 0;
}
J - Just A Minim
输入输出
//2020.4
//j
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 5e3 + 5;
int n,cnt[50];
int main() {
cin >> n;
for (int i = 1;i <= n;i++) {
int x;cin >> x;
cnt[x]++;
}
double ans = cnt[0] * 2 + cnt[1] * 1 + cnt[2] * 0.5 + cnt[4] * 0.25 + cnt[8] * 0.125 + cnt[16] * 0.0625;
cout << fixed<<setprecision(7)<<ans << endl;
return 0;
}
K - Knightsbridge Rises
感觉和上面那个Education有点像。。
//2020.4
//k
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 105;
struct P{
int w, l;
}p[maxn];
struct ANS {
int cnt;
int book[maxn];
}ans[maxn];
bool used[maxn];
int n, m,t[maxn],cnt;
bool f = 1;
void print() {
for (int i = 1;i <= m;i++) {
for (int j = ans[i].cnt;j>=1;j--) {
cout << ans[i].book[j] << " ";
}
cout << endl;
}
}
int main() {
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> p[i].w >> p[i].l;
if (p[i].w == 0) cnt++;
}
cin >> m;
for (int i = 1;i <= m;i++) cin >> t[i];
if (cnt < m) {
cout << "impossible" << endl;
return 0;
}
//dfs(1,t[1]);
for (int i = 1;i <= m;i++) {
int need = t[i];
while (need > 0) {
int find = 0x3f3f3f, pos = 0;
for (int j = 1;j <= n;j++) {
if (p[j].l >= need && !used[j]) {
if (p[j].l < find) {
find = p[j].l;
pos = j;
}
}
}
if (!pos) {
f = 0;break;
}
need = p[pos].w;
ans[i].book[++ans[i].cnt] = pos;
used[pos] = 1;
}
if (!f) break;
}
if (!f) cout << "impossible" << endl;
else print();
return 0;
}
TLE - 1的dfs
放出来搞笑一下
//2020.4
//k
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include<iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 105;
struct P{
int w, l;
}p[maxn];
struct ANS {
int cnt;
int book[maxn];
}ans[maxn];
bool used[maxn];
int n, m,t[maxn],cnt;
bool f = 0;
void print() {
for (int i = 1;i <= m;i++) {
for (int j = ans[i].cnt;j>=1;j--) {
cout << ans[i].book[j] << " ";
}
cout << endl;
}
}
void dfs(int id, int need) {
if (f) return;
if (id > m) {
f = 1;
print();
return;
}
for (int i = 1;i <= n;i++) {
if (!used[i] && p[i].l >= need) {
used[i] = 1;
ans[id].book[++ans[id].cnt] = i;
if (p[i].w == 0) dfs(id + 1, t[id + 1]);
else dfs(id, p[i].w);
ans[id].cnt--;
used[i] = 0;
}
}
}
int main() {
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> p[i].w >> p[i].l;
if (p[i].w == 0) cnt++;
}
cin >> m;
for (int i = 1;i <= m;i++) cin >> t[i];
if (cnt < m) {
cout << "impossible" << endl;
return 0;
}
dfs(1, t[1]);
if (!f) cout << "impossible" << endl;
return 0;
}
5.17的练习
最近没怎么做题,菜的很明显。
开的是
**
2012-2013 Pacific Northwest Region Programming Contest
A- Good Versus Evil
题目错了。是10,不是11
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define INF 0x3fffffff
#define mk make_pair
using namespace std;
typedef unsigned long long ll;
const int maxn = 1005;
int good[10] = { 1,2,3,3,4,10 };
int evil[10] = { 1,2,2,2,3,5,10 };
int n;
int main() {
cin >> n;
for (int i = 1;i <= n;i++) {
int g = 0, e = 0,x;
for (int j = 0;j < 6;j++) {
cin >> x;
g += good[j] * x;
}
for (int j = 0;j < 7;j++) {
cin >> x;
e += evil[j] * x;
}
cout << "Battle " << i << ": ";
if (g > e) {
cout << "Good triumphs over Evil" << endl;
}
else if (g == e) {
cout << "No victor on this battle field" << endl;
}
else {
cout << "Evil eradicates all trace of Good" << endl;
}
}
}
B-Magic Multiple
还以为是大数乘法orz
暴力
(一)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string>
#include<string.h>
#define inf 2e9
using namespace std;
long long n;
int flag[10];
bool check(long long x) {
int tmp[100], cnt = 0;
while (x) {
tmp[++cnt] = x % 10;
x /= 10;
}
for (int i = 1;i <= cnt;i++)
flag[tmp[i]] = 1;
int res = 0;
for (int i = 0;i < 10;i++)
res += flag[i];
return res == 10;
}
int main() {
while (cin >> n) {
for (int i = 0;i < 10;i++) flag[i] = 0;
for (int i = 1;;i++) {
if (check(i*n)) {
cout << i << endl;
break;
}
}
}
}
(二)大数乘法-顺便整理下模板
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define INF 0x3fffffff
#define mk make_pair
using namespace std;
typedef unsigned long long ll;
const int maxn = 1005;
int a[maxn];//数组的长度不会超过len1+len2,第一位有进位则长度是len1+len2,没有则是len1+len2-1
int len1, len2, lena;
int flag[10];
string s1, s2,tt;
string tostring(int x) {
string tmp = "";
while (x) {
tmp += '0'+x % 10;
x /= 10;
}
reverse(tmp.begin(), tmp.end());
return tmp;
}
bool check() {
s1 = tt;
memset(a, 0, sizeof(a));
//cout << s1 << " * " << s2 <<" = ";
len1 = s1.length(), len2 = s2.length(), lena = len1 + len2;
for (int i = 0;i < len1;i++) {
for (int j = 0;j < len2;j++) {
a[i + j + 1] += (s1[i] - '0')*(s2[j] - '0');
//竖式乘法规则第i位和第j位相乘位于i+j位,这里后推了一位,放进位,没有进位a【0】=0
}
}
//处理进位
for (int i = lena - 1;i > 0;i--) {
a[i - 1] += a[i] / 10;
a[i] %= 10;
}
if (a[0]) { flag[a[0]] = 1;}
for (int i = 1;i < lena;i++) {
flag[a[i]] = 1;
}
int res = 0;
for (int i = 0;i < 10;i++) {
res += flag[i];
}
return res == 10;
}
int main() {
while (cin >> s1) {
memset(flag, 0, sizeof(flag));
for (int i = 1;;i++) {
tt = s1; s2 = tostring(i);
if (check()) {
cout << i << endl;
break;
}
}
}
}
G - Saruman’s Level Up
这题挺好的,题意:
给出n,求小于等于n的数的二进制表示中1的个数能被3整除的个数有多少。
注意开ll,然后是(队友的话)类似于数位dp的思想;
我自己写的话,感觉类似于分段求解。
如果高位为1,那么后面可以挑选一些数位和这个高位组成3的倍数。
(只是此处需要保证挑出来的数位比原来的要小才可以)
怎样满足这个条件?只有1位后面的数字可以任意安排,所以我们从高到低(这样可以保证递减)遍历所有的1,让它和后面的数位构成满足的情况;当然此时我们不仅要考虑当前的1,还要计算一个bit(代表所有的1);
最后加一特判,即判断n本身是否符合条件
距离:10110111
首位为1,此时bit=0,进入循环,在剩余7位中任取3个1:C73+ C76=42;
第3位1,此时bit=1,进入循环,在剩余5位中任取2个1(2+bit),与第一个1组成,C52 + C55 = 11;
第4位1,此时bit=2,进入循环,在剩余4位中任取1个1(1+bit),与前两个1组成,C41+C44=5;
第6位1,此时bit=3,进入循环,剩余的只有两位,凑不出3个,C30=1
所以是42+11+5+1=59
最后,本身也是,59+1=60
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define INF 0x3fffffff
#define mk make_pair
using namespace std;
typedef unsigned long long ll;
const int maxn = 1005;
ll n,ans = 0;
int cnt1 = 0;
ll cnm(ll a, ll b) {
ll res = 1;
if (b > a) return 0;
for (ll i = b;i >= 1;i--) {
res = res * (a - i + 1) / (b - i + 1);
}
return res;
}
int main() {
while (cin >> n) {
ll cnt = n;
string t;
while (n) {
t+= char('0'+ n % 2);
n /= 2;
}
ans = 0;
reverse(t.begin(), t.end());
ll bit = 0;
//cout << t << endl;
for (int i = 0;i <t.length();i++) {
if(t[i]=='1'){
for (int k = 0;k < 600;k++) {
if ((k + bit) && (k + bit) % 3 == 0) {
// cout << "Have " << bit << " 1s + " << k << endl;
// cout << t.length() - i - 1 << "中 选择" << k << " 个" << endl;
ans += cnm(t.length()-i-1, k);
}
}
bit++;
}
}
//cout <<"bit: "<< bit << endl;
if (bit && bit % 3 == 0)ans++;
cout << "Day "<<cnt<<": Level = "<<ans << endl;
}
return 0;
}
另一种写法–来源网络
ll cnt = n,bit=0;
ll k = (ll)1 << 60, r = 60;
while (k) {
//n的r位为1
if (k&n) {
for (int i = 0;i <= r;i++) {
if (i + bit && (i + bit) % 3 == 0) {
ans += cnm(r,i);
cout << r << " " << i << endl;
}
}
bit++;
}
k = k >> 1;
r--;
}
//cout <<"bit: "<< bit << endl;
if (bit && bit % 3 == 0)ans++;
H-Seating Chart
转化成逆序数就好了
树状数组怎么T了?
下面这是归并,板子题
(一)归并
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define INF 0x3fffffff
#define mk make_pair
using namespace std;
typedef unsigned long long ll;
const int maxn = 2e5+5;
int N, a[maxn],b[maxn];
ll cnt;
map<string, int> mp;
void mergeSort(int l, int r) {
int mid = (l + r) >> 1;
if (l < mid) mergeSort(l, mid);
if (mid + 1 < r) mergeSort(mid + 1, r);
int i = l, j = mid + 1;
for (int k = l;k <= r;k++) {
if (i > mid) b[k] = a[j++];
else if (j > r) b[k] = a[i++];
else {
if (a[j] < a[i]) {
b[k] = a[j++];
cnt += mid - i + 1;
}
else {
b[k] = a[i++];
}
}
}
for (int i = l;i <= r;i++) a[i] = b[i];
}
int main() {
while (scanf_s("%d", &N) && N){
cnt = 0;
string x;
if (!mp.empty())mp.clear();
for (int i = 0;i < N;i++) {
cin >> x;
mp[x] = i;
}
for (int i = 0;i < N;i++) {
cin >> x;
a[i] = mp[x];
}
mergeSort(0, N - 1);
printf("%lld\n", cnt);
}
return 0;
}
(二)maxn又忘记改了,我好气
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define INF 0x3fffffff
#define mk make_pair
using namespace std;
typedef unsigned long long ll;
const int maxn = 2e5+5;
//求逆序个数(树状数组)
/*开一数组c,c[a]=0,代表a此前从未出现过;c[a]=1,代表a之前出现过。
想要求a的逆序数,只要查找[a+1,maxn]中1的个数即可,最后累加
树状数组可以优化这个过程:
每插入第i个数A,统计小于等于它的个数getsumm(A),
那么在这之前数字中,
比他大的个数是i-getsum(A)*/
int N;
int a[maxn], b[maxn];
int c[maxn];
ll cnt;
map<string, int> mp;
int lowbit(int x) {
return x & -x;
}
void update(int i, int ans) {
while (i <= N) {
c[i] += ans;
i += lowbit(i);
}
}
int sum(int i) {
int res = 0;
while (i) {
res += c[i];
i -= lowbit(i);
}
return res;
}
//b为辅助数组
int main() {
while (scanf_s("%d", &N) && N) {
cnt = 0;
string x;
if (!mp.empty())mp.clear();
for (int i = 1;i <= N;i++) {
cin >> x;
mp[x] = i;c[i] = 0;
}
for (int i = 1;i <= N;i++) {
cin >> x;
a[i] = mp[x];
}
for (int i = 1;i <= N;i++) {
update(a[i], 1);
cnt += i - sum(a[i]);
}
printf("%lld\n", cnt);
}
return 0;
}
J - Temple Build
题意:给定一个棱台??,截面是一个等腰梯形,
三种正方体填充,求最大的容量。
是 背包DP
DP,以高度dp
用到了等腰梯形的相似三角形,梦回高中
三选一,注意初始化 和 更新答案。
最后答案未必是H处的,要遍历
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string>
#include<string.h>
#define inf 2e9
using namespace std;
const int maxn = 3e6 + 5;
#define ll long long
ll dp[maxn],a[5];
ll sd, xd, H,ans;
ll cal(ll h, ll x) {
double res = (xd*(H - h) + h * sd) / (1.0*H);
res /= x;
return floor(res);
}
int main() {
while (cin >> H >> xd >> sd) {
for (int i = 0;i <= H;i++) {
dp[i] = 0;
}
ans = 0;
for (int i = 0;i < 3;i++)cin >> a[i];
for (int h = 1;h <= H;h++) {
for (int k = 0;k < 3;k++) {
if (h < a[k]) continue;
int num = cal(h,a[k]);
dp[h] = max(dp[h], dp[h - a[k]] + a[k] * a[k] * a[k] * num*num);
}
ans = max(ans, dp[h]);
}
cout << ans << endl;
}
return 0;
}
L - Tongues
水
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string>
#include<string.h>
#define inf 2e9
using namespace std;
const int maxn = 3e6 + 5;
string s;
char u[10] = { 'a', 'i', 'y', 'e', 'o', 'u'};
char al[30] = { 'b','k','x','z','n','h','d','c','w','g','p','v','j','q','t','s','r','l','m','f' };
int isu(char x) {
for (int i = 0;i < 6;i++) if (x == u[i]) return i;
return -1;
}
int iso(char x) {
for (int i = 0;i < 20;i++)
if (x == al[i]) return i;
return -1;
}
int main() {
while (getline(cin, s)) {
for (int i = 0;i < s.length();i++) {
bool f = 0;char t = s[i],now=t;
if (t >= 'A'&& t <= 'Z') { f = 1; t -= ('A' - 'a'); }
if (isu(t)!=-1) now = u[(isu(t) + 3) % 6];
else if(iso(t)!=-1) now = al[(iso(t) + 10) % 20];
if (f) now += ('A' - 'a');
cout << now;
}
cout << endl;
}
return 0;
}