솔루션은 다음과 같은 문제점을 포함한다 : \ (A \ \ \ B \ \ \ C \ \ \ D \ \ \ E \ \ \ J \)
또 : \ (\이 완료 [H] 숫자 쌍 DP \) 결국, 나는하지 않습니다
대회 주소 : https://ac.nowcoder.com/acm/contest/887#question
[A] 문자열 표현 최소
섹션들의 주어진 문자열 최소한으로 받아 최저 문자열 표시 출력 세그먼트 후의 문자열.
순차적으로 연속 단축 길이까지 다시 앞에서 열거 현재 프리픽스 작은 표현 개시 판정로부터의 출력 전류의 끝에서 다시 할 수있다.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
char s[205];
string temp;
int l;
int get_min() {
int i = 0, j = 1;
int k = 0;
while(i < l && j < l && k < l) {
int t = temp[(i+k)%l] - temp[(j+k)%l];
if(t == 0) {
k ++;
}
else {
if(t > 0) {
i = i + k + 1;
}
else {
j = j + k + 1;
}
k = 0;
if(i == j) {
j ++;
}
}
}
return i < j ? i : j;
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%s", s);
int n = strlen(s);
int pos = 0;
while(1) {
temp = "";
for(int i = pos; i < n; i++) {
temp = temp + s[i];
}
l = temp.length();
while(get_min() != 0) {
l--;
}
pos = pos + l;
for(int i = 0; i < l; i ++) {
cout << temp[i];
}
if(pos == n) {
printf("\n");
break;
}
else {
printf(" ");
}
}
}
return 0;
}
【B】 기약 다항식 数学
단항 감안할 때 \을 (N \) 그는 곱셈 형태로 그것을 무너 뜨리는 수 있다면 시간 방정식 물었다.
정리 질문이 필요한 두 개의 동일한 판정 할 수 1과 동일보다 3 배에 반드시 동일하지 \ (b ^ 2 - 4ac < 0 \) 확립되거나 확립 된 경우, 수있다.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int a[30];
int main() {0;
}
int t;
scanf("%d", &t);
while(t--) {
int n;
scanf("%d", &n);
for(int i = n; i >= 0; i--) {
scanf("%d", &a[i]);
}
if(n >= 3) {
printf("No\n");
continue;
}
if(n == 1) {
printf("Yes\n");
continue;
}
if(a[1]*a[1]-4*a[0]*a[2] < 0) {
printf("Yes\n");
}
else {
printf("No\n");
}
}
return 0;
}
[C] 욕심 모래 통치
우리가 보지 않을 때 나는 왜 게임을 모른다 "C를 <= 200"도, 학교도 형제 구덩이를 많은 시간을 낭비했다하더라도이 조건이, 그의 동료는, 트리 선 두께의 유지 보수를 노크 ... 다음은 (아마도) 작성하는 경기 후 긍정적 인 솔루션입니다.
감안 \ (n \) 나무의 높이가 각각 \ (H (\ leq1e ^ 9) \) 의 비용을 줄일 \ (c (\ 당량 200) \) 와 수 \ (\ (p를 1E ^ 9 당량) \) . 이제 우리는 나무의 가장 높은 숫자가 최소가 비용이 얼마나 물어 50 % 이상을 차지 얻을 필요가있다.
사실, 여러 가지가 잘 욕심 정렬.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5+5;
int n;
ll sum[maxn];
ll cost[205];
ll numh[maxn];
vector<ll> v;
struct node {
ll h, c, p;
bool operator < (const node &q) const {
return h < q.h;
}
}a[maxn];
int getid(ll x) {
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
int main() {
while(~scanf("%d", &n)) {
v.clear();
for(int i = 1; i <= n; i++) {
scanf("%lld%lld%lld", &a[i].h, &a[i].c, &a[i].p);
v.push_back(a[i].h);
}
sort(a+1, a+1+n);
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
memset(sum, 0, sizeof(sum));
memset(numh, 0, sizeof(numh));
for(int i = 1; i <= n; i++) {
int id = getid(a[i].h);
sum[id] += sum[id-1] + 1ll*a[i].p*a[i].c;
numh[id] += numh[id-1] + 1ll*a[i].p;
}
ll ans = 1e18;
memset(cost, 0, sizeof(cost));
int new_n = v.size();
for(int i = 1; i <= n; i++) {
int id = getid(a[i].h);
ll temp = sum[new_n] - sum[id]; // 删掉所有比它高的树的代价
ll num = numh[id] - numh[id-1]; // 这种高度的树的数量
ll num_small = numh[id-1]; // 比他矮的树的数量
// cout << temp << " " << num << " " << num_small << endl;
if(num > num_small) { // 不用砍了
ans = min(ans, temp);
cost[a[i].c] += 1ll*a[i].p;
continue;
}
ll more = num_small - num + 1; // 需要砍掉多少
for(int j = 1; j <= 200; j++) {
if(cost[j] == 0) {
continue;
}
if(more - cost[j] >= 0) {
more -= cost[j];
temp = temp + cost[j]*j;
}
else {
temp = temp + more*j;
more = 0;
}
if(more == 0) {
break;
}
}
cost[a[i].c] += 1ll*a[i].p;
ans = min(ans, temp);
}
printf("%lld\n", ans);
}
return 0;
}
[D] 번호 물 문제
물 문제는 쓰지 않는다.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int get(int x) {
int res = 0;
while(x) {
res++;
x /= 10;
}
return res;
}
int main() {
int n, p;
while(~scanf("%d%d", &n, &p)) {
int l = get(p);
if(l > n) {
printf("T_T\n");
continue;
}
printf("%d", p);
for(int i = l+1; i <= n; i++) {
printf("0");
}
printf("\n");
}
return 0;
}
[E]는 중간 세그먼트 트리 찾기
참조 : http://keyblog.cn/article-189.html
포인팅 대상이 실제로 두 배열을 L, R, 및 빈 서열, 제 주어진 \ (I는 \)를 LR 위해이 투입 \ ([L_i가 R_i] \ ) 시퀀스의 각 숫자를 첨가하고있다 현재 시퀀스의 중간 출력.
주요 문제는 일부 + 1 / -1은 매우 쉬운 실수이 특히 내 사용됩니다 작성하는 것입니다 \ (벡터 \) 이산, 나는 -1 삽입하자 처음부터 첨자 1, 어떤 식 으로든보다 더 있었다 배열은 + 1 / -1의 많은 것을 회피 할 수 있습니다. 코드에서 구현 모습입니다.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 8e5+5;
ll x[maxn], y[maxn];
ll val[maxn<<2], lazy[maxn<<2];
vector<ll> v;
int getid(ll x) {
return lower_bound(v.begin(), v.end(), x) - v.begin();
}
void pushup(int rt) {
val[rt] = val[rt<<1] + val[rt<<1|1];
}
void pushdown(int l, int r, int rt) {
int mid = (l+r) >> 1;
val[rt<<1] += (v[mid]-v[l])*lazy[rt];
val[rt<<1|1] += (v[r]-v[mid])*lazy[rt];
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
void build(int l, int r, int rt) {
if(l == r) {
val[rt] = lazy[rt] = 0;
return ;
}
int mid = (l+r) >> 1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
pushup(rt);
}
void update(int L, int R, int l, int r, int rt) {
if(L <= l && r-1 <= R) {
val[rt] += (v[r]-v[l]);
lazy[rt] ++;
return ;
}
if(lazy[rt]) {
pushdown(l, r, rt);
}
int mid = (l+r) >> 1;
if(L < mid) {
update(L, R, l, mid, rt<<1);
}
if(R >= mid) {
update(L, R, mid, r, rt<<1|1);
}
pushup(rt);
}
ll query(int l, int r, int rt, ll x) { // 找第 x 大的数
if(l == r-1) {
ll t = val[rt] / (v[r]-v[l]);
return v[l] + (x-1)/t;
}
if(lazy[rt]) {
pushdown(l, r, rt);
}
int mid = (l+r) >> 1;
if(val[rt<<1] >= x) {
return query(l, mid, rt<<1, x);
}
else {
return query(mid, r, rt<<1|1, x-val[rt<<1]);
}
}
int main() {
int n;
scanf("%d", &n);
v.clear();
ll a1, b1, c1, m1;
ll a2, b2, c2, m2;
scanf("%lld%lld%lld%lld%lld%lld", &x[1], &x[2], &a1, &b1, &c1, &m1);
scanf("%lld%lld%lld%lld%lld%lld", &y[1], &y[2], &a2, &b2, &c2, &m2);
for(int i = 3; i <= n; i++) {
x[i] = (a1*x[i-1]+b1*x[i-2]+c1) % m1;
y[i] = (a2*y[i-1]+b2*y[i-2]+c2) % m2;
}
for(int i = 1; i <= n; i++) {
ll tx = x[i];
ll ty = y[i];
x[i] = min(tx, ty) + 1;
y[i] = max(tx, ty) + 1 + 1; // 多 +1 方便区间操作
v.push_back(x[i]);
v.push_back(y[i]);
}
v.push_back(-1);
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int new_n = v.size();
ll sum = 0;
build(1, new_n, 1);
for(int i = 1; i <= n; i++) {
int l = getid(x[i]);
int r = getid(y[i]);
update(l, r-1, 1, new_n, 1);
sum = sum + (v[r] - v[l]);
printf("%lld\n", query(1, new_n, 1, (sum+1)/2));
}
return 0;
}
[J], A + B 문제 표제 물
사실은 정말 내 카드를 넣어, 결국 그것을 물 문제를 호출 할, 분명히 10 라인이 뭔가를 얻을 수없는, 뇌가 빠른 펌핑이 100 선을 썼다 ... 다음 코드는 제목의 게임을 만드는 방법을 오랫동안 알고 지출
물 문제는 쓰지 않는다.
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
ll f(ll x) {
ll res = 0;
while(x) {
res = res*10 + x%10;
x /= 10;
}
return res;
}
int main() {
ll a, b;
int t;
scanf("%d", &t);
while(t--) {
scanf("%lld%lld", &a, &b);
printf("%lld\n", f(f(a)+f(b)));
}
return 0;
}