NOIP模拟3
A. 三元
把 内的数写出来,发现要最高位 都留 个,那么字典序的限制只对 有用,把前 个 开头写出来
然后每次按位变成
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 200005;
int n, L;
struct tre{
int a[18], num;
void init(int x){
int p = 0;
while(x){
a[p++] = x % 3;
x /= 3;
}
}
void print(){
for(int i = L - 1; i >= 0; --i)printf("%d",a[i]);
printf("\n");
}
void get_num(){
int s = 1;num = 0;
for(int i = 0; i < L; ++i){
num += s * a[i];
s *= 3;
}
}
tre dec(){
tre b;
for(int i = L - 1; i >= 0; --i)b.a[i] = (a[i] + 4) % 3;
return b;
}
friend bool operator < (const tre &x, const tre &y){
return x.num < y.num;
}
}a[maxn];
int main(){
freopen("three.in","r",stdin);
freopen("three.out","w",stdout);
n = read(), L = read();
int now = 1;
for(int i = 1; i < L; ++i)now = now * 3; now = now * 2;
for(int i = 1; i <= n; ++i){a[i].init(now); ++now;}
for(int i = 1; i <= n; ++i)a[i + n] = a[i].dec(), a[i + n + n] = a[i + n].dec();
for(int i = 1; i <= n + n + n; ++i)a[i].get_num();
sort(a + 1, a + n + n + n + 1);
for(int i = 1; i <= n + n + n; ++i)a[i].print();
return 0;
}
B. 鹅国
因为没有注意数据范围会炸 寄掉
直接暴力,加上两个小剪枝,不知道复杂度对不对,感觉挺优的,不过更希望有人能够卡掉,或者严谨证明
正解从别人博客里翻吧
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 1005;
int n, k; ll p;
ll c[maxn], w[maxn];
unordered_map<ll ,ll>mp[1005], tmp[1005];
int cnt;
void Ckmx(ll &x, ll y){if(y > x)x = y;}
void Ckmi(ll &x, ll y){if(x == 0 || x > y)x = y;}
typedef pair<ll, ll> pll;
vector<ll>vec;
int main(){
// freopen("goose.in","r",stdin);
// freopen("goose.out","w",stdout);
n = read(), k = read(), p = read();
for(int i = 1; i <= n; ++i)c[i] = read(), w[i] = read();
for(int i = n; i >= 1; --i){
if(c[i] + (__int128)(k - 1) * c[1] > p)continue;
mp[1][c[i]] = w[i];
tmp[1][c[i]] = w[i];
for(int j = 1; j < k; ++j){
__int128 mx = p - (__int128)c[1] * (k - j), mi = p - (__int128)c[i] * (k - j);
vec.clear();
for(auto x : mp[j])if(x.first < mi || x.first > mx)vec.push_back(x.first);
for(ll x : vec)mp[j].erase(x), tmp[j].erase(x);
for(auto x : mp[j])if(p - x.first >= c[i])Ckmi(mp[j + 1][x.first + c[i]], x.second + w[i]);
for(auto x : tmp[j])if(p - x.first >= c[i])Ckmx(tmp[j + 1][x.first + c[i]], x.second + w[i]);
}
}
if(mp[k][p] == 0){
printf("-1\n");
return 0;
}
printf("%lld %lld\n",mp[k][p], tmp[k][p]);
printf("%d\n",cnt);
return 0;
}
C. 楼盘
暂时弃
code
D. 矩形
容易计算 的矩形数量,于是可以二分,不知道赛时为啥
二分得到 的值以后,可以查询值介于 之间的矩形数量以及大小,因为只查询了有用的,所以总复杂度是 大概?
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll read(){
ll x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 3000005;
ll n, h[maxn], L, R;
int l[maxn], r[maxn], sta[maxn], top;
ll calc(ll s, ll w){return s < 0 || w < 0 ? 0 : (s + w) * (s - w + 1) / 2;}
ll sum(int i, ll mx){return mx <= 0 ? 0 : calc(r[i] - l[i] + 1 , r[i] - l[i] + 1 - min(mx, r[i] - l[i] + 1ll) + 1) - calc(i - l[i], i - l[i] - min(mx, i - l[i] + 0ll) + 1) - calc(r[i] - i, r[i] - i - min(mx, r[i] - i + 0ll) + 1);}
ll check(ll mid){
ll ans = 0;
for(int i = 1; i <= n; ++i)if(r[i] - l[i] + 1)ans += sum(i, mid / h[i]);
return ans;
}
ll solve(ll q){
ll ansl = 1, ansr = 3e14, ans = -1;
while(ansl <= ansr){
ll mid = (ansl + ansr) >> 1;
if(check(mid) >= q)ansr = mid - 1, ans = mid;
else ansl = mid + 1;
}
return ans;
}
vector<ll>ans;
void get(ll pl, ll pr){
if(pl > pr)return;
for(int i = 1; i <= n; ++i){
for(ll len = (pl + h[i] - 1) / h[i]; len * h[i] <= pr && len <= r[i] - l[i] + 1; ++len){
ll num = sum(i, len) - sum(i, len - 1);
for(int p = 1; p <= num; ++p)ans.push_back(h[i] * len);
}
}
}
void sol(){
for(int i = 1; i <= n; ++i){
while(top && h[sta[top]] > h[i])--top;
l[i] = sta[top] + 1; sta[++top] = i;
}
sta[top = 0] = n + 1;
for(int i = n; i >= 1; --i){
while(top && h[sta[top]] >= h[i])--top;
r[i] = sta[top] - 1; sta[++top] = i;
}
ll lval = solve(L), rval = solve(R);
ll clval = check(lval);
for(ll i = L; i <= clval && ans.size() < R - L + 1; ++i)ans.push_back(lval);
get(lval + 1, rval - 1);
while(ans.size() < R - L + 1)ans.push_back(rval);
sort(ans.begin(), ans.end());
for(ll x : ans)printf("%lld ",x);
}
int main(){
freopen("rectangle.in","r",stdin);
freopen("rectangle.out","w",stdout);
n = read();
for(int i = 1; i <= n; ++i)h[i] = read();
L = read(), R = read();
sol();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】