Preface
最近板刷比赛都跟着bzt神仙的节奏来啊,看到他在打Comet OJ 所以我也来打了
看比赛榜就知道这一次前5题都很多人过但F无人AC,bzt说正解是LCT优化长链剖分,我立刻就不想写了QAQ
A 杀手皇后
SB题不解释
#include
#include
using namespace std;
int n; string s,ans;
int main()
{
ios::sync_with_stdio(0); cin>>n;
for (register int i=1;i<=n;++i) cin>>s,(ans==""||s
B 支援城市
把平方拆了发现我们只需要维护\(\sum_{i=1}^n w_i^2\)和\(\sum_{i=1}^n w_i\)就可以对于每一个\(xO(1)\)计算了
#include
using namespace std;
const int N=100005;
int n,a[N]; long long sum,psum;
int main()
{
register int i; for (scanf("%d",&n),i=1;i<=n;++i)
scanf("%d",&a[i]),sum+=a[i],psum+=1LL*a[i]*a[i];
for (i=1;i<=n;++i) printf("%lld ",psum+1LL*n*a[i]*a[i]-2LL*sum*a[i]);
return 0;
}
C
首先发现符文石无论怎样合并最后的答案都是一样的,因此我们先把从左到右的答案全算出来
然后考虑可以精炼一个区间,那么我们发现这个区间的两端都乘上了一个\(k-1\)的系数,然后中间的数乘上了\(k^2-1\)的系数
那我们直接DP设\(f_i\)为包含\(i\)的答案,每次按\(i\)为左右中三个位置更新答案即可
#include
#include
#define RI register int
using namespace std;
const int N=100005;
int n,k,a[N],b[N]; long long f[N],ret,dlt;
int main()
{
RI i; for (scanf("%d%d",&n,&k),i=1;i<=n;++i)
{
scanf("%d%d",&a[i],&b[i]); ret+=b[i-1]*a[i];
dlt=min(dlt,f[i-1]+1LL*(k-1)*b[i-1]*a[i]);
f[i]=min(f[i],min(1LL*(k-1)*b[i-1]*a[i],f[i-1]+1LL*(k*k-1)*b[i-1]*a[i]));
}
return printf("%lld",ret+dlt),0;
}
D 菜菜种菜
bzt神仙刚开始用sort然后T掉了,所以我就学乖了没有sort……
首先我们考虑对于每一块菜地预处理出编号比它小的最大值\(l_i\)以及编号比它大的最小值\(r_i\),那么一个区间\([L,R]\)合法当且仅当\(l_i
所以现在我们相当于要计算\(\sum_{i=L}^R [l_i
考虑我们按序枚举\(L\),每次再将\(L-1\)位置上的所有\(l_i=L-1\)的\(i\)的\([i,r_i-1]\)区间加上\(s_i\),然后将\(i=L-1\)的\([i,r_i-1]\)的\(s_i\)扣去,再查询\(R\)上的值即为答案
用树状数组+vector即可维护上述过程,复杂度\(O(n\log n)\)(树状数组的\(\log\)快到难以想象)
#include
#include
#include
#include
#include
#define RI register int
#define CI const int&
#define Tp template
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=1e6+5;
typedef pair pi;
typedef vector ::iterator VP;
int n,m,q,l[N],r[N],x,y,a[N],ans[N],mx; long long ret; vector et[N],ques[N];
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
#define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))
char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[15];
public:
Tp inline void read(T& x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
Tp inline void write(T x)
{
RI ptop=0; while (pt[++ptop]=x%10,x/=10);
while (ptop) pc(pt[ptop--]+48); pc('\n');
}
#undef tc
#undef pc
}F;
class Tree_Array
{
private:
int bit[N];
#define lowbit(x) x&-x
inline void add(RI x,CI mv)
{
for (;x<=n;x+=lowbit(x)) bit[x]+=mv;
}
public:
inline void modify(CI l,CI r,CI mv)
{
if (l>r) return; add(l,mv); add(r+1,-mv);
}
inline int query(RI x,int ret=0)
{
for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
}
#undef lowbit
}BIT;
int main()
{
//freopen("D.in","r",stdin); freopen("D.out","w",stdout);
RI i; for (F.read(n),F.read(m),F.read(q),i=1;i<=n;++i) F.read(a[i]),r[i]=n+1;
for (i=1;i<=m;++i) F.read(x),F.read(y),yx&&(r[x]=min(r[x],y));
for (i=1;i<=q;++i) F.read(x),F.read(y),ques[x].pb(mp(y,i)),mx=max(mx,y);
for (i=1;i<=n;++i) et[l[i]].pb(mp(r[i],i)); for (i=1;i<=mx;++i)
{
for (VP it=et[i-1].begin();it!=et[i-1].end();++it)
BIT.modify(it->se,it->fi-1,a[it->se]); BIT.modify(i-1,r[i-1]-1,-a[i-1]);
for (VP it=ques[i].begin();it!=ques[i].end();++it) ans[it->se]=BIT.query(it->fi);
}
for (i=1;i<=q;++i) ret^=1LL*i*ans[i]; return printf("%lld",ret),0;
}
E 神奇函数
神仙数论题,首先我们冷静分析一下\(f(x)\)的本质就是求\(x\)在分解质因数之后将每个质因子的次数除以\(2\)(下取整)
这个很好理解,我们观察第二个式子,发现就是一个不停提出质因数的过程
所以我们发现\(f(x)\)的值域就是根号级别的,我们可以枚举\(f(x)\)的值,然后算出有多少个数的值为这个
实际上,我们可以得出关于答案的这样一个式子:
\[ans=\sum_{i=1}^{\sqrt n} i\cdot g(\frac{n}{i^2})\]
其中\(g(x)\)表示\([1,x]\)内不含有平方因子的数的个数
为什么是这个函数呢,很简单,因为一旦它有了平方因子那个因子就可以被提出来,所以值就不是当前的值了
考虑\(g(x)=\sum_{i=1}^x \mu(i)^2\),运用一下经典容斥就会发现它其实是\(\sum_{i=1}^{\sqrt{x}}\mu(i)\cdot \lfloor\frac{n}{i^2}\rfloor\)
这样这题大致就可以做了,我们对于枚举答案的一层和计算\(g(x)\)的时候都除法分块一下,复杂度就是\(O(n^{\frac{2}{3}})\)的
如果直接这样写就会T掉好多点,因此我们还要预处理一下\(\le 10^7\)的\(g(x)\),直接回答即可
#include
#include
#include
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int N=1e7;
int t,prime[N+5],cnt,mu[N+5],g[N+5]; bool vis[N+5]; LL n,ans;
#define Pi prime[j]
inline void init(CI n)
{
RI i,j; for (mu[1]=vis[1]=1,i=2;i<=n;++i)
{
if (!vis[i]) prime[++cnt]=i,mu[i]=-1;
for (j=1;j<=cnt&&i*Pi<=n;++j)
{
vis[i*Pi]=1; if (i%Pi) mu[i*Pi]=-mu[i]; else break;
}
}
for (i=1;i<=n;++i) g[i]=g[i-1]+mu[i]*mu[i];
for (i=1;i<=n;++i) mu[i]+=mu[i-1];
}
#undef Pi
inline LL G(const LL& x)
{
if (x<=N) return g[x];
int lim=sqrt(x); LL ret=0; for (RI l=1,r;l<=lim;l=r+1)
r=min(lim,(int)sqrt(x/(x/(1LL*l*l)))),ret+=1LL*(mu[r]-mu[l-1])*(x/(1LL*l*l));
return ret;
}
inline LL sum(CI l,CI r)
{
return 1LL*(l+r)*(r-l+1)>>1LL;
}
int main()
{
//freopen("E.in","r",stdin); freopen("E.out","w",stdout);
for (init(N),scanf("%d",&t);t;--t)
{
scanf("%lld",&n); int lim=sqrt(n); ans=0; for (RI l=1,r;l<=lim;l=r+1)
r=min(lim,(int)sqrt(n/(n/(1LL*l*l)))),ans+=1LL*sum(l,r)*G(n/(1LL*l*l));
printf("%lld\n",ans);
}
return 0;
}
F 黄金体验
LCT优化长链剖分,谁爱写谁写
咕咕咕
Postscript
比赛体验还好,算是混了个平均水平吧(感谢B指导和陈指导的指导)