A. Mike and Cellphone
给出按手机键盘的顺序,判断号码是否唯一。
必须同时有按键出现在键盘的边缘,号码才会唯一。0也算边缘。
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 4e5 + 50;
const int MAXM = 2e5 + 50;
int n;
char s[10];
int main() {
#ifdef LOCAL_NORTH
FIN;
#endif // LOCAL_NORTH
while (~scanf("%d%s", &n, s)) {
int ok1 = 0, ok2 = 0, ok3 = 0, ok4 = 0;
for (int i = 0; s[i]; i++) {
if (s[i] >= '1' && s[i] <= '3') {
ok1 = 1;
}
if (s[i] == '7' || s[i] == '0' || s[i] == '9') {
ok2 = 1;
}
if (s[i] == '1' || s[i] == '4' || s[i] == '7' || s[i] == '0') {
ok3 = 1;
}
if (s[i] == '3' || s[i] == '6' || s[i] == '9' || s[i] == '0') {
ok4 = 1;
}
}
printf("%s\n", ok1 + ok2 + ok3 + ok4 == 4 ? "YES" : "NO");
}
#ifdef LOCAL_NORTH
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
return 0;
}
B. Mike and Shortcuts
一个从1到n的序列,从i可以到达i-1,i+1,以及a[i],每走一次消耗一点能量。输出从1出发到达每个点的最短消耗。
这题想也没想就dij了。。。其实O(n)的bfs更简单。。。
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;
int n, a[MAXN];
struct Edge {
int to, w, nxt;
}E[MAXN << 2];
int Head[MAXN], tot;
void edge_init() {
tot = 0;
memset(Head, -1, sizeof(Head));
}
void edge_add(int u, int v, int w) {
E[tot].to = v;
E[tot].w = w;
E[tot].nxt = Head[u];
Head[u] = tot++;
}
struct Node {
int v, val;
Node(int vv, int vval) {
v = vv;
val = vval;
}
bool operator < (const Node& node) const {
return val > node.val;
}
};
int mincost[MAXN];
bool vis[MAXN];
void dijkstra(int start) {
memset(mincost, INF, sizeof(mincost));
memset(vis, false, sizeof(vis));
priority_queue<Node> q;
while (!q.empty())
q.pop();
mincost[start] = 0;
q.push(Node(start, 0));
while (!q.empty()) {
Node cur = q.top();
q.pop();
int u = cur.v;
if (vis[u])
continue;
vis[u] = true;
for (int i = Head[u]; ~i; i = E[i].nxt) {
int v = E[i].to;
if (!vis[v] && mincost[v] > mincost[u] + E[i].w) {
mincost[v] = mincost[u] + E[i].w;
q.push(Node(v, mincost[v]));
}
}
}
}
int main() {
#ifdef LOCAL_NORTH
FIN;
#endif // LOCAL_NORTH
while (~scanf("%d", &n)) {
edge_init();
for (int i = 1; i <= n; i++) {
if (i != 1) {
edge_add(i, i - 1, 1);
edge_add(i - 1, i, 1);
}
int v;
scanf("%d", &v);
edge_add(i, v, 1);
}
dijkstra(1);
for (int i = 1; i <= n; i++) {
printf("%d%c", mincost[i], " \n"[i == n]);
}
}
#ifdef LOCAL_NORTH
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
return 0;
}
C. Mike and Chocolate Thieves
给出一个n,输出一个最小的m。m要满足a*k^3<=m(a,k>0)的个数刚好等于n。
直接二分答案。对于mid,我们判断的方法:从1开始枚举k(k^3>n时break),对于每一个k,满足条件的a的个数就是mid/(k^3)。累加然后判断累加之和与n的关系即可。
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;
LL m;
LL work(LL n) {
LL res = 0;
for (LL i = 2; i <= INFLL; i++) {
LL t = i * i * i;
if (t > n)
break;
res += n / t;
}
return res;
}
int main() {
#ifdef LOCAL_NORTH
FIN;
#endif // LOCAL_NORTH
while (~scanf("%I64d", &m)) {
LL l = 1, h = INFLL, ans = -1;
while (l <= h) {
LL mid = (l + h) / 2;
LL t = work(mid);
if (t >= m) {
if (t == m) {
ans = mid;
}
h = mid - 1;
} else {
l = mid + 1;
}
}
printf("%I64d\n", ans);
}
#ifdef LOCAL_NORTH
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
return 0;
}
D. Friends and Subsequences
给出两个序列,输出a序列区间内最大值等于b序列区间内最小值的区间个数。
二分+RMQ。
首先可以知道,于是就有了单调性。
具体就是枚举左端点l,二分右端点r,求出满足=0的最小的rmin和最大的rmax(与lower_bound和upper_bound组合使用来计数的方法类似),然后ans+=rmax-rmin。区间最值可以用RMQ实现O(1)查询。
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define lowbit(x) ((x)&(-x))
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e6 + 3;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;
int n, a[MAXN], b[MAXN];
int dpa[MAXN][20], dpb[MAXN][20];
int mm[MAXN];
void initRMQ(int n) {
mm[0] = -1;
for(int i = 1; i <= n; i++) {
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dpa[i][0] = a[i];
dpb[i][0] = b[i];
}
for(int j = 1; j <= mm[n]; j++)
for(int i = 1; i + (1<<j) -1 <= n; i++) {
dpa[i][j] = max(dpa[i][j-1],dpa[i+(1<<(j-1))][j-1]); //max可以改为任何积性函数
dpb[i][j] = min(dpb[i][j-1],dpb[i+(1<<(j-1))][j-1]);
}
}
int rmq(int x,int y) {
int k = mm[y-x+1];
return max(dpa[x][k],dpa[y-(1<<k)+1][k]) - min(dpb[x][k],dpb[y-(1<<k)+1][k]);
}
int main() {
#ifdef LOCAL_NORTH
FIN;
#endif // LOCAL_NORTH
while (~scanf("%d", &n)) {
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
scanf("%d", &b[i]);
initRMQ(n);
LL ans = 0;
for (int i = 1; i <= n; i++) {
int l = i, h = n, a, b;
while (l <= h) {
int mid = (l + h) / 2;
if (rmq(i, mid) >= 0) //lower_bound
h = mid - 1;
else
l = mid + 1;
}
a = l - 1;
l = i, h = n;
while (l <= h) {
int mid = (l + h) / 2;
if (rmq(i, mid) > 0) //upper_bound
h = mid - 1;
else
l = mid + 1;
}
b = l - 1;
ans += (b - a);
}
printf("%I64d\n", ans);
}
#ifdef LOCAL_NORTH
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
return 0;
}
E. Mike and Geometry Problem
给出n个区间,求穷举k个区间相交,相交部分的整数个数。
离散化+组合数。
对于一个点i,如果有cnt个区间覆盖了它,那么它对最终答案的贡献就是。但是逐个枚举i是不可能的。
所以先把区间的左右端点离散化后排序。排序后的相邻两个数所组成的区间内的点,被覆盖的次数是相同的。所以用last来记录上一个端点,ans+=C(cnt,k)* (当前端点坐标-last)。O(n)枚举就好了。
还要注意一点,左端点记录的时候要减1,这样就能正确地计算[1,3]∩[3,5]这种情况了。
/*
::
:;J7, :, ::;7:
,ivYi, , ;LLLFS:
:iv7Yi :7ri;j5PL
,:ivYLvr ,ivrrirrY2X,
:;r@Wwz.7r: :ivu@kexianli.
:iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur
ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17
;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i
:,, ,,: ,::ir@mingyi.irii:i:::j1jri7ZBOS7ivv,
,::, ::rv77iiiriii:iii:i::,rvLq@huhao.Li
,, ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:
::: ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri
, 2OBBOi,iiir;r:: ,irriiii::,, ,iv7Luur:
,, i78MBBi,:,:::,:, :7FSL: ,iriii:::i::,,:rLqXv::
: iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::
, ::::i ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii
, : , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:
, ,,,,::::i: @arqiao. ,:,, ,:::ii;i7:
:, rjujLYLi ,,:::::,:::::::::,, ,:i,:,,,,,::i:iii
:: BBBBBBBBB0, ,,::: , ,:::::: , ,,,, ,,:::::::
i, , ,8BMMBBBBBBi ,,:,, ,,, , , , , , :,::ii::i::
: iZMOMOMBBM2::::::::::,,,, ,,,,,,:,,,::::i:irr:i:::,
i ,,:;u0MBMOG1L:::i:::::: ,,,::, ,,, ::::::i:i:iirii:i:i:
: ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::
: :rk@Yizero.i:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,
: 5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i@petermu.,
, :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::
:jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:
,: :@kevensun.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,
,,, ,,:,::::::i:iiiii:i::::,, ::::iiiir@xingjief.r;7:i,
, , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::
:,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;@Secbone.ii:::
*****************************************************************************
Singing my song for my dream.
*****************************************************************************
*/
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
typedef pair<int,int> PII;
#define mp make_pair
#define pb push_back
#define FIN freopen("in.txt", "r", stdin);
#define FOUT freopen("out.txt", "w", stdout);
#define lson l, mid, cur << 1
#define rson mid + 1, r, cur << 1 | 1
#define lowbit(x) ((x)&(-x))
#define bitcnt(x) __builtin_popcount(x)
#define bitcntll(x) __builtin_popcountll(x)
#define debug puts("-------------");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const double ERR = 1e-8;
const int MOD = 1e9 + 7;
const int MAXN = 2e5 + 50;
const int MAXM = 2e5 + 50;
int n, k;
LL fac[MAXN];
vector<PII > seg;
LL fastpow(LL b, LL c) {
LL res = 1;
while (c) {
if (c & 1)
res = res * b % MOD;
b = b * b % MOD;
c >>= 1;
}
return res;
}
LL C(LL m, LL n) {
if (n > m)
return 0;
LL up = fac[m], down = fac[n] * fac[m - n] % MOD;
return up * fastpow(down, MOD - 2) % MOD;
}
int main() {
#ifdef LOCAL_NORTH
FIN;
#endif // LOCAL_NORTH
fac[0] = 1;
for (int i = 1; i < MAXN; i++)
fac[i] = fac[i - 1] * i % MOD;
while (~scanf("%d%d", &n, &k)) {
seg.clear();
for (int i = 0; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
seg.pb(mp(a - 1, 1));
seg.pb(mp(b, -1));
}
sort(seg.begin(), seg.end());
LL ans = 0;
int sz = seg.size(), last = seg[0].first, cnt = 0;
for (int i = 0; i < sz; i++) {
ans = (ans + C(cnt, k) * (seg[i].first - last)) % MOD;
last = seg[i].first;
cnt += seg[i].second;
}
printf("%I64d\n", ans);
}
#ifdef LOCAL_NORTH
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // LOCAL_NORTH
return 0;
}