Educational Codeforces Round 89 (Rated for Div. 2)
D.Two Divisors
#include<bits/stdc++.h>
using namespace std;
const int N=500010;
int n;
int a[N];
int b[N];int c[N];
const int V=10000010;
int lp[V];int prime[1000010];int tot_prime=0;
void seive(){
int v=V-1;
for(int i=2;i<=v;i++){
if(!lp[i]){lp[i]=i;prime[++tot_prime]=i;}
for(int j=1;j<=tot_prime&&i*prime[j]<=v;j++){
lp[i*prime[j]]=prime[j];
}
}
}
signed main(){
std::ios::sync_with_stdio(false);
seive();
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
b[i]=-1;c[i]=-1;
int j=lp[a[i]];
while(a[i]%j==0)a[i]/=j;
if(a[i]>1){
b[i]=j;c[i]=a[i];
}
}
for(int i=1;i<=n;i++)cout<<b[i]<<" ";cout<<'\n';
for(int i=1;i<=n;i++)cout<<c[i]<<" ";cout<<'\n';
}
E - Two Arrays
b[j]递增,所以如果a[i]被划分到b[j]这一段,a[i]的后缀最小值<=b[i]
切m-1刀,第j刀可以切在所有的a[i]==b[j+1]后
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
const int p=998244353;
map<int,int> mp;
const int N=200010;
int n,m;int a[N];int b[N];
signed main(){
std::ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
a[n+1]=0x3f3f3f3f;for(int i=n;i>=1;i--){a[i]=min(a[i],a[i+1]);mp[a[i]]++;}
for(int i=1;i<=m;i++)cin>>b[i];
if(a[1]!=b[1]){
cout<<0;//如果头一个区间的最小值不能满足
return 0;
}
int ans=1;
for(int i=2;i<=m;i++){
ans=(ans*mp[b[i]])%p;
}
cout<<ans;
}
F. Jog Around The Graph
容易发现\(O(n^2)\)dp,\(f[j][i]\)表示以i为结束点,走了长为j的路径的最大总权值
\(f[j][i]=max(f[j-1][i1]+w,f[j][i])\)前\(m\)步为\(O(m*m)\)
q无穷大时一直反复走权值最大的边最优。\(q>=m\),\(m\)步之内必然能到达所有边,m步之后q无穷大时反复走这条边
但是不是权值最大的边任何时候都更优,它增长快,但是可能走到它的权值截距非常地小
\(f[j][v]=mx_v*(j-m)+f[m][v]\)q减去m后,\(mx_v\)为斜率,\(f[m][v]\)为直径。
考虑维护凸包,找出每条线作为最高的区间
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
const int P=1e9+7;
const int N=2010;
int n,m,q;
vector<pair<int,int>> G[N];
int m1,u1,v1;
int f[N][N];
struct EDGE{
int u,v,w;
}e[N];int k[N];int b[N];
signed main(){
std::ios::sync_with_stdio(false);
cin>>n>>m>>q;
for(int i=1;i<=m;i++){
int u,v,w;cin>>u>>v>>w;G[u].push_back({v,w});G[v].push_back({u,w});
e[i].u=u;e[i].v=v;e[i].w=w;
if(m1<w){
m1=w;u1=u;v1=v;
}
}
//m=q;
for(int j=0;j<=m;j++)for(int i=1;i<=n;i++)f[j][i]=-0x3f3f3f3f;
f[0][1]=0;
for(int j=1;j<=m;j++){
for(int i=1;i<=n;i++){
for(auto [i1,w]:G[i]){
f[j][i]=max(f[j][i],f[j-1][i1]+w);
}
}
}
int ans=0;int mx=0;
for(int j=1;j<=m;j++){
int tem=0;
for(int i=1;i<=n;i++){
tem=max(tem,f[j][i]);
}
// cout<<"get"<<j<<" "<<tem<<'\n';
ans=(ans+tem)%P;
if(j==m)mx=tem;
}
q-=m;
for(int i=1;i<=m;i++){//斜率截距
k[i]=e[i].w;b[i]=max(f[m][e[i].u],f[m][e[i].v]);
}
for(int i=1;i<=m;i++){
int l=1;int r=q;//这一条线作为最高的区间
for(int j=1;j<=m;j++){
if(i!=j){
if(k[i]>k[j]){
l=max(l,(b[j]-b[i])/(k[i]-k[j])+1);
}else if(k[i]<k[j]){
r=min(r,(b[j]-b[i])/(k[i]-k[j]));
}else {//斜率相同
if(b[i]>b[j])continue;//i优
if(b[i]==b[j]&&i<=j)continue;//i优
l=q+1;//i永远在j下面
}
}
}
if(l>r)continue;
ans=(ans+((l+r)*(r-l+1)/2)%P*k[i]%P)%P;
ans=(ans+b[i]*(r-l+1)%P)%P;
}
//ans=(ans+mx*(q-m)%P)%P;
//ans=(ans+m1*((1+q-m)*(q-m)/2)%P%P)%P;
cout<<ans<<'\n';
}

浙公网安备 33010602011771号