AtCoder Beginner Contest 353
A - Buildings
求第一个 \(h_i\) 大于 \(h_1\) 的位置。
模拟。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,h[103];
signed main(){
cin>>n;cin>>h[1];
for(int i=2;i<=n;i++){
cin>>h[i];
if(h[i]>h[1]) cout<<i,exit(0);
}
cout<<"-1";
return 0;
}
B - AtCoder Amusement Park
有若干容量为 \(k\) 的车,每个组只能坐一辆车,求按顺序坐车需要的车辆数。
模拟。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,a[103],cnt,v;
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
if(v+a[i]<=k) v+=a[i];
else v=a[i],cnt++;
}
cout<<cnt+1;
return 0;
}
C - Sigma Problem
令 \(f(x,y)=(x+y)\bmod 10^8\)。
求
\[\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^nf(a_i,a_j)
\]
\(1\le a_i<10^8\)。
这个数据范围是关键。
先考虑排序,然后对于每个 \(i\) 找到第一个 \(j\) 使得 \(a_i+a_j>10^8\),贡献就为后缀和减去 \(n-j+1\) 个 \(10^8\),时间复杂度 \(O(n\log n)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
const int mod=1e8;
using namespace std;
int n,a[300003],ans,pre[300003];
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
a[n+1]=mod;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) pre[i]=pre[i-1]+a[i];
int pos=n;
for(int i=1;i<n;i++){
while(pos>i&&a[i]+a[pos]>=mod) pos--;
if(pos<i) pos=i;
ans+=a[i]*(n-i)+pre[n]-pre[i]-(n-pos)*mod;
}
cout<<ans;
return 0;
}
D - Another Sigma Problem
令 \(f(x,y)=\overline{xy}\)。
求
\[\left(\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^nf(a_i,a_j)\right)\bmod 998244353
\]
考虑一个数的贡献,就是后面的数的 \(10^{位数}\) 和加上后缀和,然后就没了,时间复杂度 \(O(n\log_{10} n)\)
点击查看代码
#include<bits/stdc++.h>
#define int long long
const int mod=998244353;
using namespace std;
int n,a[300003],ans,ton[300004],pre[300004];
int qpow(int a,int b){
int res=1;
for(;b;b>>=1,a=a*a%mod) if(b&1) res=res*a%mod;
return res;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=(pre[i-1]+a[i])%mod;
ton[i]=(ton[i-1]+qpow(10,(int)(log10l(a[i])+1))%mod)%mod;
}
for(int i=1;i<=n;i++){
ans=(ans+(pre[n]-pre[i]+(ton[n]-ton[i])*a[i]%mod+mod)%mod)%mod;
}
cout<<ans;
return 0;
}
E - Yet Another Sigma Problem
令 \(f(x,y)=\text{LCP}(x,y)\)。
求
\[\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^nf(a_i,a_j)
\]
把字符串放到 trie 树上,插入时记末端节点 \(x\),记 \(g_x\) 为 \(x\) 被几个字符串覆盖,则 \(g_x\to g_x+1\),然后对于每个节点 \(u\) 算 \(g_u=\sum\limits_{v\in \text{son}_u}g_v\)。
计算答案时可以分开计算,对于每个字符位置 \(x\),其贡献为 \(\frac{g_x(g_x-1)}{2}\)。计算即可。
不要弄错下标!时间复杂度 \(O(\sum |s|)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,ans;
char s[300003];
int trie[300004][30],node,g[300004];
void insert(){
int u=0;
for(int i=0;s[i];i++){
if(!trie[u][s[i]-'a'])
trie[u][s[i]-'a']=++node;
u=trie[u][s[i]-'a'];
}
g[u]++;
}
void dfs(int u){
int cnt=0,f=0;
for(int i=0;i<26;i++){
if(trie[u][i]){
dfs(trie[u][i]);
g[u]+=g[trie[u][i]];
}
}
}
void ds(int u){
ans+=g[u]*(g[u]-1)/2;
for(int i=0;i<26;i++){
int v=trie[u][i];
if(v){
ds(v);
}
}
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s;
insert();
}
for(int i=0;i<26;i++){
if(trie[0][i]) dfs(trie[0][i]);
}
for(int i=0;i<26;i++){
if(trie[0][i]) ds(trie[0][i]);
}
cout<<ans;
return 0;
}