AtCoder Beginner Contest 353

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;
}

posted @ 2024-05-12 11:33  view3937  阅读(28)  评论(0编辑  收藏  举报
Title