Codeforces#678 Div2
B - Prime Square
构造 \(n\times n\) 的矩阵使得每行每列都是素数且每个格子都不是。
设和为 \(p\) ,在对角线上放 \(p-n+1\) ,其余放 \(1\) ,找最小的一个 \(p\) 使得 \(p\in primes\) 且 \(p-n+1\) 不是即可。
C - Binary Search
给你一个在有序序列中二分 \(x\) 得到的位置,问无序情况下有多少种 \(n\) 的排列 “二分” \(x\) 得到的位置不变。
模拟二分过程,统计到 \(pos\) 需要 “遇到” 多少个比 \(x\) 小的,和多少个比 \(x\) 大的,剩下的位置就是随意填,然后排列组合即可。
//Author: RingweEH
const int Mod=1e9+7;
int n,x,pos;
int main()
{
n=read(); x=read(); pos=read();
int l=0,r=n,lar=0,sma=0;
while ( l<r )
{
int mid=(l+r)>>1;
if ( mid==pos ) l=mid+1;
else if ( mid>pos ) r=mid,lar++;
else l=mid+1,sma++;
}
int ans=1;
if ( sma>=x || lar>n-x ) { puts( "0" ); return 0; }
for ( int i=x-1,j=1; j<=sma; i--,j++ ) ans=1ll*ans*i%Mod;
for ( int i=n-x,j=1; j<=lar; i--,j++ ) ans=1ll*ans*i%Mod;
for ( int i=1; i<=n-sma-lar-1; i++ ) ans=1ll*ans*i%Mod;
printf( "%d\n",ans );
return 0;
}
D - Bandit in a City
转化后的题意:给定以 \(1\) 为根的 \(n\) 个节点的一棵树,每个节点上有 \(a_i\) 个人,每个人可以选择往任意子节点走,直到走到叶子节点为止,问最后人最多的叶子节点最少有多少人。
DFS 处理出子树中叶子结点个数 \(cnt\) 和人数总和 \(sum\) ,答案就是 \(\max\{\left\lceil\dfrac{sum}{cnt}\right\rceil\}\) .
//Author: RingweEH
void DFS( int u )
{
sum[u]=a[u];
for ( auto v : g[u] )
DFS(v),cnt[u]+=cnt[v],sum[u]+=sum[v];
if ( !g[u].size() ) cnt[u]=1;
ans=max( ans,(sum[u]+cnt[u]-1)/cnt[u]);
}
E - Complicated Computations
求一个数列的所有连续子数列的 \(\tt mex\) 值的 \(\tt mex\) 。
离谱题面 如果所有连续子序列的 \(\tt mex\) 集合中存在 \(x\) ,那么一定有一个子序列满足:\(1\sim x-1\) 均出现,且没有 \(x\) 。
注意到值域是 \(1e5\) ,所以考虑枚举答案,那么需要做到 \(\log\) 查询是否有区间符合条件。
设当前枚举的数为 \(x\) ,按照 \(x\) 在序列中的所有出现位置分段(和头尾、两个 \(x\) 之间),问题转化为对于每一段询问是否出现了 \(1\sim x-1\) . 设当前区间为 \([l,r]\) ,问是否出现 \(a\) ,就是在查询 \([1,r]\) 之间 \(a\) 的最后出现位置是否 \(>l\) ,维护 \(n\) 棵线段树即可。
直接做显然会炸……考虑把所有东西挂到一棵权值线段树上,叶子结点的意义(设代表了数 \(x\) )就是数 \(x\) 目前在序列中最后出现的位置,维护区间最小值。设当前遍历到区间 \([1,pos]\) ,\(las[a[pos]]\) 表示数 \(a[pos]\) 上一次出现的位置,直接查询 \(1\sim a[pos]-1\) 在线段树上的最小值,也就是 \(1\sim a[pos]-1\) 最后出现位置的最小值 \(num\) ,如果 \(num>las[a[pos]]\) 那么就符合条件。
注意最后还要统计一次所有 \(a[i]\) 到结尾的区间。
//Author: RingweEH
#define lc pos<<1
#define rc pos<<1|1
const int N=1e5+10,INF=1e6+10;
int las[N],tr[N<<2],n,a[N];
bool vis[N];
void Pushup( int pos ) { tr[pos]=min(tr[pos<<1],tr[pos<<1|1]); }
void Modify( int pos,int l,int r,int x,int val )
{
if ( x>r || x<l ) return;
if ( l==r ) { tr[pos]=val; return; }
int mid=(l+r)>>1;
Modify( lc,l,mid,x,val ); Modify( rc,mid+1,r,x,val );
Pushup( pos );
}
int Query( int pos,int L,int R,int l,int r )
{
if ( L>r || R<l ) return INF;
if ( l<=L && R<=r ) return tr[pos];
int mid=(L+R)>>1;
int res=Query(lc,L,mid,l,r); bmin( res,Query(rc,mid+1,R,l,r) );
return res;
}
int main()
{
n=read();
for ( int i=1,x; i<=n; i++ )
{
a[i]=read(); x=0;
if ( a[i]>1 ) x=Query(1,1,n,1,a[i]-1);
if ( x>las[a[i]] ) vis[a[i]]=1;
Modify(1,1,n,a[i],i); las[a[i]]=i;
}
for ( int i=2,x; i<=n+1; i++ )
{
x=Query(1,1,n,1,i-1);
if ( x>las[i] ) vis[i]=1;
}
for ( int i=1; i<=n; i++ )
if ( a[i]^1 ) vis[1]=1;
int p=1;
while ( 1 )
{
if ( !vis[p] ) { printf( "%d\n",p ); return 0; }
p++;
}
return 0;
}
F - Sum Over Subsets
求可重集 \(S\) 的两个子集 \(A,B\) 满足:
- \(B\) 是 \(A\) 的子集
- \(B\) 元素个数比 \(A\) 少一
- \(A\) 所有元素的 \(\gcd=1\)
求所有 \(\sum\limits_{x\in A}*\sum\limits_{x\in B}\bmod 998244353\) 之和,值相等的不同的元素算不同集合。
很有意思的题。\(\gcd\) 和倍数相关,那么就统计 \(g[i]\) 表示 \(\gcd\) 为 \(i\) 的倍数的答案,然后莫反变成 \(f[i]\) 表示 \(\gcd=i\) 的答案。而我们所求是 \(f[1]\) ,也就是说只需要累加所有的 \(g(x)\mu(x)\) 就好了.
对于 \(g\) ,贡献有两种:( \(k\) 表示总个数)
- \(a[i]\cdot a[i]\) ,方案数有 \(2^{k-2}\cdot (k-1)\)
- \(a[j]\cdot a[i]\) ,方案数为 \(2^{k-3}\cdot (k-2)+2^{k-2}\) ,然后再算上两个集合互换的情况。
//Author: RingweEH
int main()
{
n=read();
for ( int i=1,x; i<=n; i++ )
x=read(),a[x]=read();
mu[1]=1;
for ( int i=1; i<=N-10; i++ )
for ( int j=i+i; j<=N-10; j+=i )
mu[j]-=mu[i];
ll ans=0,cnt,sum,sumq;
for ( int i=1; i<=N-10; i++ )
{
cnt=0,sum=0,sumq=0;
for ( int j=i; j<=N-10; j+=i )
{
cnt+=a[j]; (sum+=a[j]*j%Mod)%=Mod;
(sumq+=a[j]*j%Mod*j%Mod)%=Mod;
}
if ( cnt<2 ) continue;
ll t1=sumq*power(2,cnt-2)%Mod*((cnt-1)%Mod)%Mod;
ll t2=(sum*sum%Mod+Mod-sumq)%Mod;
ll res=power(2,cnt-2);
if ( cnt>2 ) (res+=((cnt-2)%Mod)*power(2,(cnt-3)%(Mod-1))%Mod)%Mod;
res=res*t2%Mod; (res+=t1)%=Mod;
ans=(ans+res*mu[i]%Mod+Mod)%Mod;
}
printf( "%lld\n",ans );
return 0;
}

浙公网安备 33010602011771号