AtCoder Beginner Contest 445题解
D - Reconstruct Chocolate
水题,不讲不讲。
int h,w,n;
pii ans[N];
struct node{
int h,w,id;
}a[N],b[N];
bool cmp1(node u,node v){
return u.w>v.w;
}
bool cmp2(node u,node v){
return u.h>v.h;
}
void print(){
up(i,1,n){
cout<<ans[i].fi<<" "<<ans[i].se<<endl;
}
}
void dfs(int x,int y,int ida,int idb){
if(ida==n+1||idb==n+1){
print();
exit(0);
}
if(a[ida].w==w-y+1){
int res=0;
while(ida<=n){
if(ans[a[ida].id].fi==0){
ans[a[ida].id]={x+res,y};
//cout<<ans[a[ida].id].fi<<" "<<ans[a[ida].id].se<<endl;
res+=a[ida].h;
}
ida++;
if(a[ida].w!=w-y+1)break;
}
dfs(x+res,y,ida,idb);
}
else{
int res=0;
while(idb<=n){
if(ans[b[idb].id].fi==0){
ans[b[idb].id]={x,y+res};
res+=b[idb].w;
}
idb++;
if(b[idb].h!=h-x+1)break;
}
dfs(x,y+res,ida,idb);
}
}
void solve(){
cin>>h>>w>>n;
int u,v;
up(i,1,n){
cin>>u>>v;
a[i]={u,v,i};
b[i]={u,v,i};
}
sort(a+1,a+1+n,cmp1);
sort(b+1,b+1+n,cmp2);
dfs(1,1,1,1);
}
E - Many LCMs
这个题还是有点意思的。
核心是预处理出1e7范围内所有数最小的质因子。
然后对给出的2e5个数进行处理,记录每个出现的因子最大的次数和第二大的次数。
int n,a[N];
int bp[M+1];
vector<int>pri;
void init(){
iota(bp, bp+M+1, 0);
for (int x = 2; x <= M; x++){
if (bp[x] == x) pri.push_back(x);
for (auto p : pri) {
if (p * x > M || p > bp[x]) break;
bp[p * x] = p;
}
}
}
int ksm(int a,int b){
int res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void solve(){
cin>>n;
up(i,1,n){
cin>>a[i];
}
map<int,int>e1,e2;
up(i,1,n){
int x=a[i];
while(x>1){
int p=bp[x],cnt=0;
while(x%p==0){
x/=p;
cnt++;
}
if(cnt>e1[p])e2[p]=e1[p],e1[p]=cnt;
else if(cnt>e2[p])e2[p]=cnt;
}
}
int lcm=1;
for(auto [p,e]:e1)lcm=lcm*ksm(p,e)%mod;
up(i,1,n){
int x=a[i],ans=lcm;
while(x>1){
int p=bp[x],cnt=0;
while(x%p==0){
x/=p;cnt++;
}
if(cnt==e1[p]){
ans=ans*ksm(ksm(p,cnt-e2[p]),mod-2)%mod;
}
}
cout<<ans<<" ";
}
cout<<endl;
}
F - Exactly K Steps 2
min-plus 矩阵乘法。
一个有趣的知识点。
#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>
int main() {
using namespace std;
unsigned N, K;
cin >> N >> K;
vector C(N, vector<unsigned long>(N));
for (auto&& row : C)
for (auto&& c : row)
cin >> c;
// Finds results of (a + b) moves, given results of a moves and b moves
const auto prod{[N, inf{ranges::max(C | views::join) * K}](const auto& lhs, const auto& rhs) {
// Initialize with a sufficiently large value
vector ret(N, vector(N, inf));
for (const auto i : views::iota(0U, N))
for (const auto j : views::iota(0U, N))
for (const auto k : views::iota(0U, N))
ret[i][k] = min(ret[i][k], lhs[i][j] + rhs[j][k]);
return ret;
}};
auto ans(C);
--K;
// Fast exponentiation
while (K) {
if (K & 1)
ans = prod(ans, C);
C = prod(C, C);
K /= 2;
}
for (const auto i : views::iota(0U, N))
cout << ans[i][i] << endl;
return 0;
}

浙公网安备 33010602011771号