20210925衡阳八中多校联测
http://bzoj.org/d/dxlc2021/contest/614dc3a612bb0e2d50cc9f85
100+100+20+91=311,rk2。
A
枚举每个 \(a_i\) 的因数即可。\(\mathcal O(n\sqrt{a_i})\)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
map<int,int> cnt;
const int N=210;
int a[N],ans[N];
int main()
{
freopen("divisors.in","r",stdin);
freopen("divisors.out","w",stdout);
int n=read(),m=read();
for(int i=1;i<=m;i++)a[i]=read();
for(int i=1;i<=m;i++)
{
for(int j=1;j*j<=a[i];j++)
{
if(a[i]%j)continue;
if(j<=n)cnt[j]++;
if(j*j!=a[i]&&a[i]/j<=n)cnt[a[i]/j]++;
}
}
int Ans=n;
for(map<int,int>::iterator it=cnt.begin();it!=cnt.end();it++)ans[it->second]++,Ans--;
printf("%d\n",Ans);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}
B
令 \(v\) 为价值,\(w\) 为代价。注意代价很大而价值很小,所以 \(f(i,v)\) 表示前 \(i\) 个物品得到价值 \(v\) 的最小代价,每个询问二分回答即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
#define int long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
const int N=310,M=310*310,inf=0x3f3f3f3f3f3f3f3fll;
int Ans[100010],f[2][M];
struct node{int t,v,w;}a[N];
bool cmp(node x,node y){return x.t<y.t;}
struct Query{int t,w,pos;}q[100010];
bool cmp1(Query x,Query y){return x.t<y.t;}
int Min[M];
signed main()
{
freopen("market.in","r",stdin);
freopen("market.out","w",stdout);
int n=read(),m=read(),vv=300*300;
for(int i=1;i<=n;i++)a[i].w=read(),a[i].v=read(),a[i].t=read();
sort(a+1,a+n+1,cmp);
// puts("SHOPS:");
// for(int i=1;i<=n;i++)printf("w=%lld, v=%lld, t=%lld\n",a[i].w,a[i].v,a[i].t);
for(int i=1;i<=m;i++)q[i].t=read(),q[i].w=read(),q[i].pos=i;
sort(q+1,q+m+1,cmp1);
memset(f,0x3f,sizeof(f));
memset(Min,0x3f,sizeof(Min));
f[0][0]=0,a[n+1].t=inf;
for(int i=1,j=1;i<=n;i++)
{
for(int j=0;j<=vv;j++)f[i&1][j]=inf;
for(int j=vv;j>=0;j--)
{
f[i&1][j]=f[(i&1)^1][j];
if(j>=a[i].v)f[i&1][j]=min(f[i&1][j],f[(i&1)^1][j-a[i].v]+a[i].w);
}
for(int j=vv;j>=0;j--)Min[j]=min(Min[j+1],f[i&1][j]);
for(;j<=m&&q[j].t<a[i+1].t;j++)
{
if(q[j].t<a[i].t)continue;
int L=0,R=vv,pos=0;
while(L<=R)
{
int mid=(L+R)>>1;
if(Min[mid]<=q[j].w)pos=mid,L=mid+1;
else R=mid-1;
}
Ans[q[j].pos]=pos;
}
}
for(int i=1;i<=m;i++)printf("%lld\n",Ans[i]);
}
C
设连通块 \(A\) 的直径为 \(u_0-v_0\),\(B\) 为 \(u_1-v_1\),那两个连通块 \(A,B\) 合并时直径一定是这四个点中的两个组成的路径,那么线段树分治即可,并查集维护一下直径端点。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<bitset>
#include<cstdlib>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
void write(int n)
{
if(n>9)write(n/10);
putchar(n%10^48);
}
const int N=70010,M=N<<1;
int head[N],ver[M],nxt[M],tot=0,n,m;
void add(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
bool vis[N];int t,fa[N][30],dep[N];
void bfs(int s)
{
queue<int> que;
que.push(s);
vis[s]=dep[s]=1;
while(!que.empty())
{
int x=que.front();que.pop();
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];if(vis[y])continue;
que.push(y),fa[y][0]=x;
for(int j=1;j<=t;j++)fa[y][j]=fa[fa[y][j-1]][j-1];
vis[y]=1,dep[y]=dep[x]+1;
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
if(dep[fa[x][16]]>=dep[y])x=fa[x][16];
if(dep[fa[x][15]]>=dep[y])x=fa[x][15];
if(dep[fa[x][14]]>=dep[y])x=fa[x][14];
if(dep[fa[x][13]]>=dep[y])x=fa[x][13];
if(dep[fa[x][12]]>=dep[y])x=fa[x][12];
if(dep[fa[x][11]]>=dep[y])x=fa[x][11];
if(dep[fa[x][10]]>=dep[y])x=fa[x][10];
if(dep[fa[x][9]]>=dep[y])x=fa[x][9];
if(dep[fa[x][8]]>=dep[y])x=fa[x][8];
if(dep[fa[x][7]]>=dep[y])x=fa[x][7];
if(dep[fa[x][6]]>=dep[y])x=fa[x][6];
if(dep[fa[x][5]]>=dep[y])x=fa[x][5];
if(dep[fa[x][4]]>=dep[y])x=fa[x][4];
if(dep[fa[x][3]]>=dep[y])x=fa[x][3];
if(dep[fa[x][2]]>=dep[y])x=fa[x][2];
if(dep[fa[x][1]]>=dep[y])x=fa[x][1];
if(dep[fa[x][0]]>=dep[y])x=fa[x][0];
if(x==y)return x;
if(fa[x][16]!=fa[y][16])x=fa[x][16],y=fa[y][16];
if(fa[x][15]!=fa[y][15])x=fa[x][15],y=fa[y][15];
if(fa[x][14]!=fa[y][14])x=fa[x][14],y=fa[y][14];
if(fa[x][13]!=fa[y][13])x=fa[x][13],y=fa[y][13];
if(fa[x][12]!=fa[y][12])x=fa[x][12],y=fa[y][12];
if(fa[x][11]!=fa[y][11])x=fa[x][11],y=fa[y][11];
if(fa[x][10]!=fa[y][10])x=fa[x][10],y=fa[y][10];
if(fa[x][9]!=fa[y][9])x=fa[x][9],y=fa[y][9];
if(fa[x][8]!=fa[y][8])x=fa[x][8],y=fa[y][8];
if(fa[x][7]!=fa[y][7])x=fa[x][7],y=fa[y][7];
if(fa[x][6]!=fa[y][6])x=fa[x][6],y=fa[y][6];
if(fa[x][5]!=fa[y][5])x=fa[x][5],y=fa[y][5];
if(fa[x][4]!=fa[y][4])x=fa[x][4],y=fa[y][4];
if(fa[x][3]!=fa[y][3])x=fa[x][3],y=fa[y][3];
if(fa[x][2]!=fa[y][2])x=fa[x][2],y=fa[y][2];
if(fa[x][1]!=fa[y][1])x=fa[x][1],y=fa[y][1];
if(fa[x][0]!=fa[y][0])x=fa[x][0],y=fa[y][0];
return fa[x][0];
}
int dist(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
int u[N],v[N],L[N],R[N],Ans[N];
struct dsu
{
int fa[N],sz[N],a[N],b[N],top,d[N];
pii st[N],p[N];
//st.first:father, st.second:son
void init(int n){for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1,a[i]=i,b[i]=-1,d[i]=0;}
int getf(int x){return fa[x]==x?x:getf(fa[x]);}
dsu(){top=0;}
void mg(int x,int y)
{
int fx=getf(x),fy=getf(y);
if(sz[fx]>sz[fy])
{
st[++top]=mp(fx,fy);
p[top]=mp(a[fx],b[fx]);
fa[fy]=fx;
sz[fx]+=sz[fy];
int l=0,r=0,dis=-1;
if(~a[fx]&&~b[fx]&&dist(a[fx],b[fx])>dis)dis=dist(a[fx],b[fx]),l=a[fx],r=b[fx];
if(~a[fx]&&~a[fy]&&dist(a[fx],a[fy])>dis)dis=dist(a[fx],a[fy]),l=a[fx],r=a[fy];
if(~a[fx]&&~b[fy]&&dist(a[fx],b[fy])>dis)dis=dist(a[fx],b[fy]),l=a[fx],r=b[fy];
if(~b[fx]&&~a[fy]&&dist(b[fx],a[fy])>dis)dis=dist(b[fx],a[fy]),l=b[fx],r=a[fy];
if(~b[fx]&&~b[fy]&&dist(b[fx],b[fy])>dis)dis=dist(b[fx],b[fy]),l=b[fx],r=b[fy];
if(~a[fy]&&~b[fy]&&dist(a[fy],b[fy])>dis)dis=dist(a[fy],b[fy]),l=a[fy],r=b[fy];
d[fx]=dis,a[fx]=l,b[fx]=r;
}
else
{
st[++top]=mp(fy,fx);
p[top]=mp(a[fy],b[fy]);
fa[fx]=fy;
sz[fy]+=sz[fx];
int l=0,r=0,dis=-1;
if(~a[fx]&&~b[fx]&&dist(a[fx],b[fx])>dis)dis=dist(a[fx],b[fx]),l=a[fx],r=b[fx];
if(~a[fx]&&~a[fy]&&dist(a[fx],a[fy])>dis)dis=dist(a[fx],a[fy]),l=a[fx],r=a[fy];
if(~a[fx]&&~b[fy]&&dist(a[fx],b[fy])>dis)dis=dist(a[fx],b[fy]),l=a[fx],r=b[fy];
if(~b[fx]&&~a[fy]&&dist(b[fx],a[fy])>dis)dis=dist(b[fx],a[fy]),l=b[fx],r=a[fy];
if(~b[fx]&&~b[fy]&&dist(b[fx],b[fy])>dis)dis=dist(b[fx],b[fy]),l=b[fx],r=b[fy];
if(~a[fy]&&~b[fy]&&dist(a[fy],b[fy])>dis)dis=dist(a[fy],b[fy]),l=a[fy],r=b[fy];
d[fy]=dis,a[fy]=l,b[fy]=r;
}
}
void back()
{
sz[st[top].fi]-=sz[st[top].se];
fa[st[top].se]=st[top].se;
a[st[top].fi]=p[top].fi;
b[st[top].fi]=p[top].se;
d[st[top].fi]=dist(p[top].fi,p[top].se);
top--;
}
}B;
struct sgt
{
vector<int>vec[N<<2];
struct seg
{int l,r;}t[N<<2];
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)return;
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
void modify(int p,int l,int r,int d)
{
if(l<=t[p].l&&t[p].r<=r)
{
vec[p].pb(d);
return;
}
int mid=(t[p].l+t[p].r)/2;
if(l<=mid)modify(p*2,l,r,d);
if(r>mid)modify(p*2+1,l,r,d);
}
void dfs(int p,int ans)
{
int pre=vec[p].size();
for(int i=0;i<vec[p].size();i++)
B.mg(u[vec[p][i]],v[vec[p][i]]),ans=max(ans,B.d[B.getf(u[vec[p][i]])]);
if(t[p].l==t[p].r)
{
Ans[t[p].l]=ans;
for(int i=0;i<vec[p].size();i++)B.back();
return;
}
dfs(p*2,ans),dfs(p*2+1,ans);
for(int i=0;i<vec[p].size();i++)B.back();
}
}T;
int main()
{
freopen("ds.in","r",stdin);
freopen("ds.out","w",stdout);
n=read(),m=read();
for(int i=1;i<n;i++){u[i]=read(),v[i]=read(),L[i]=read(),R[i]=read();add(u[i],v[i]),add(v[i],u[i]);}
t=16,bfs(1);
B.init(n);
T.build(1,1,n);
for(int i=1;i<n;i++)T.modify(1,L[i],R[i],i);
T.dfs(1,0);
for(int i=1;i<=m;i++)write(Ans[read()]),putchar('\n');
}
D
\(\mathcal O(n^2)\) 的做法就是枚举连续的乘法段,两边都是加号,算出现次数,就是 \(\sum_{i\le j} 2^{\max\{i-2,0\}}\cdot 2^{\max\{n-j-1,0\}}\cdot\prod_{k=i}^ja_k\)。注意到把 \(j\) 弄出来的话对于每个 \(j\) 的贡献是一个形如 \(\sum \left(2^{x}\prod a_i\right)\) 的形式,这是可以线性推出来的,预处理个 \(2^x\) 就可以 \(\mathcal O(n)\)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
const int mod=1e9+7,N=1e5+10;
int qpow(int a,int n)
{
int ans=1;
while(n)
{
if(n&1)ans=1ll*a*ans%mod;
a=1ll*a*a%mod;
n>>=1;
}
return ans;
}
int sum[N],inv[N],a[N];
int main()
{
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
sum[0]=inv[0]=1;
int n=read();for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)sum[i]=1ll*sum[i-1]*a[i]%mod,inv[i]=qpow(sum[i],mod-2);
int ans=0;
int s=0;
for(int i=1;i<=n;i++)
{
s=(1ll*s*a[i]%mod+1ll*a[i]*qpow(2,max(i-2,0))%mod)%mod;
ans=(ans+1ll*s*qpow(2,max(n-i-1,0))%mod)%mod;
}
printf("%d",ans);
}