人生第一次ak了bc, 当然要写个题解装逼一下。。(其实是题水。。。)
Hdu 5198 Strang Class
水题。。 不过wa了两发。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define mxn 100020
#define LL long long
#define inf 0x3f3f3f3f
#define MP make_pair
char s[mxn];
int n;
bool check(int l, int r) {
for(int i = l; i <= r; ++i)
if(s[i] != s[l]) return 0;
return 1;
}
int main() {
while(scanf("%s", s + 1) != EOF) {
n = strlen(s + 1);
if(n % 3 != 0) {
puts("NO");
continue;
}
int x = n / 3 + 1;
int y = n / 3 * 2 + 1;
int z = n / 3;
if(check(1, 1 + z - 1) && check(x, x + z - 1) && check(y, y + z - 1)) {
if(s[1] != s[x] && s[1] != s[y] && s[x] != s[y])
puts("YES");
else
puts("NO");
}
else
puts("NO");
}
return 0;
}
Hdu 5199 Gunner
也是水题, 离散化一下, 再加个输入挂就ok了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define mxn 1000200
#define LL long long
#define inf 0x3f3f3f3f
#define MP make_pair
int n, m;
int a[mxn];
int readint() {
char c;
while((c = getchar()) && !(c >= '0' && c <= '9'));
int ret = c - '0';
while((c = getchar()) && (c >= '0' && c <= '9'))
ret = ret * 10 + c - '0';
return ret;
}
int san[mxn], cnt;
bool vis[mxn];
int f(int v) {
int k = lower_bound(a + 1, a + n + 1, v) - a;
if(k > n || a[k] != v)
return 0;
return 1;
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 1; i <= n; ++i) a[i] = readint();
memset(vis, 0, sizeof vis);
sort(a + 1, a + n + 1);
while(m--) {
int v;
v = readint();
if(f(v) == 0) {
puts("0");
continue;
}
int p = lower_bound(a + 1, a + n + 1, v) - a;
if(vis[p]) {
puts("0");
continue;
}
else {
int y = upper_bound(a + 1, a + n + 1, v) - a;
vis[p] = 1;
printf("%d\n", y - p);
}
}
}
return 0;
}
Hdu 5200 Trees
题意:
给n个数, 树高为hi, q次询问, 每次询问把小于等于v的树都去掉, 剩下的树分成了几块。
思路:
正向处理的话用线段树是比较麻烦的, 但是如果离线的话, 按照询问从小到达来处理就比较容易。
把一个树去掉的话, 如果它的旁边没有树的话, 分块数要减少1, 如果有两棵树的话, 分块数加1, 否则不变。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define mxn 50020
#define LL long long
#define inf 0x3f3f3f3f
#define MP make_pair
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
struct query {
int x, id, ans;
bool operator < (const query &b) const {
return x < b.x;
}
}s[mxn];
bool cmp(query a, query b) {
return a.id < b.id;
}
int n, q;
struct node {
int h, p;
bool operator < (const node &b) const {
return h < b.h;
}
}a[mxn];
bool c[mxn];
int main() {
while(scanf("%d%d", &n, &q) != EOF) {
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i].h);
a[i].p = i;
}
sort(a + 1, a + n + 1);
for(int i = 1; i <= q; ++i) {
scanf("%d", &s[i].x);
s[i].id = i;
}
sort(s + 1, s + q + 1);
int ans = 1;
memset(c, true, sizeof c);
int j = 1;
for(int i = 1; i <= q; ++i) {
while(j <= n && a[j].h <= s[i].x) {
int h = a[j].p;
int cnt = 0;
if(h > 1 && c[h-1]) ++cnt;
if(h < n && c[h+1]) ++cnt;
if(cnt == 2) ++ans;
else if(cnt == 0) --ans;
c[h] = 0;
++j;
}
s[i].ans = ans;
}
sort(s + 1, s + q + 1, cmp);
for(int i = 1; i <= q; ++i)
printf("%d\n", s[i].ans);
}
return 0;
}
Hdu 5201 The Monkey King
题意:
要把n个桃子分给m个猴子, 其中第一个猴子的桃子要严格最多的, 问方案数。
思路:
可以枚举分多少个桃子给第一个猴子, 假设为x, 那么分给其他猴子的桃子假设为a[i], 那么
a[2] + a[3] + ... + a[m-1] = n - x, 如果没有限制的话, 答案就是f(n-x, m-1), f(x, y) 表示把x个桃子分给y个猴子的方案,显然f(x, y) = C(x + y - 1, x), C是组合数。
有限制的话, 可以根据容斥, 算出总的,然后减去1个猴子比第一个猴子的桃子多的方案,然后加上2个猴子比第一个猴子多的方案。。。
k个猴子比第一个猴子多的方案是C(m-1, k) * f(n - (k + 1) * x, m - 1)。
然后加起来就可以了。
刚开始sb了, 以为这么算复杂度是n^2。
其实每个x, 都是只有O(n/x)次计算的, 因为n - (k + 1) * x < 0时候就跳出循环, 所以复杂度和筛法那样。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define mxn 200020
#define LL long long
#define inf 0x3f3f3f3f
#define MP make_pair
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define mod 1000000007
LL fac[mxn], nfac[mxn];
LL qpow(LL x, int k) {
LL ret = 1;
while(k) {
if(k & 1) ret = ret * x % mod;
x = x * x % mod;
k >>= 1;
}
return ret;
}
void init() {
fac[0] = fac[1] = nfac[0] = nfac[1] = 1;
for(int i = 2; i < mxn; ++i) {
fac[i] = fac[i-1] * i % mod;
nfac[i] = qpow(fac[i], mod - 2);
}
}
int n, m;
LL C(int x, int y) {
if(y < 0 || y > x) return 0;
return fac[x] * nfac[y] % mod * nfac[x-y] % mod;
}
LL f(int r, int k) {
return C(r + k - 1, r);
}
LL calc(LL x) {
LL ret = 0;
for(int k = 0; (k + 1) * x <= n; ++k) {
LL t = C(m - 1, k) * f(n - (k + 1) * x, m - 1) % mod;
if(k & 1)
ret = ((ret - t) % mod + mod) % mod;
else
ret = (ret + t) % mod;
}
return ret;
}
int main() {
init();
int cas;
scanf("%d", &cas);
while(cas--) {
scanf("%d%d", &n, &m);
if(m == 1) {
printf("%d\n", 1);
continue;
}
int t = n / m;
if(n % m == 0) ++t;
else if(n % m != 1) t += 2;
LL ans = 0;
for(int i = max(1, t); i <= n; ++i) {
ans = (ans + calc(i)) % mod;
}
printf("%I64d\n", ans);
}
return 0;
}