五一练习(5.1 & 5.17)

今天开的是 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值