2021ccpc预选

A

签到题,分别计算两种情况边的贡献,注意奇偶性的影响

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,ans,x;
int main()
{
	rep(T,1,read())
	{
		n=read();ans=n-n/2;
		x=(n+2)/3;if(x&1) ans++,x++;
		ans+=(n-x+1)/2;
		printf("%d\n",ans);
	}
}

B

先将整个串处理出来,寻找合法区间可以简单用滑动窗口维护

容易发现\(n\times lcm(len_1,\cdots,len_n)\)为一个周期,而\(lcm\)很小

由于字符串是循环的,因此考虑到\([0,2lcm]\)区间即一定存在答案

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 6001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
int n,m,lcm,len[110],pos,sum[26],tot,vis[26],now,ans;
char ch[110][15],s[MAXN];
inline void mdf(int x,int w)
{
	sum[x]+=w;
	if(w>0&&sum[x]==1) now++;
	if(w<0&&!sum[x]) now--;
}
int main()
{
	int g;rep(T,1,read())
	{
		n=read();lcm=pos=1;m=tot=now=0;ans=inf;
		rep(i,0,25) vis[i]=sum[i]=0;
		rep(i,1,n)
		{
			scanf("%s",ch[i]);len[i]=strlen(ch[i]);
			g=__gcd(lcm,len[i]),lcm=lcm/g*len[i];
			rep(j,0,len[i]-1) if(!vis[ch[i][j]-'a']) vis[ch[i][j]-'a']=1,tot++;
		}
		rep(i,0,lcm*2-1) rep(j,1,n) s[++m]=ch[j][i%len[j]];
		rep(i,1,m) 
		{
			mdf(s[i]-'a',1);
			for(;now==tot;pos++) ans=min(ans,i-pos+1),mdf(s[pos]-'a',-1);
		}
		printf("%d\n",ans);
	}
}

E

令矩阵\(A=\begin{bmatrix}b&c\\ 1&0\end{bmatrix}\)\(B=\begin{bmatrix}d&e\\ 1&0\end{bmatrix}\),容易得到\(\begin{bmatrix}f(i+j,i)\\...\end{bmatrix}=B^{j}A^{i-1}\begin{bmatrix}a\\ 0\end{bmatrix}=\begin{bmatrix}B^j_{1,1}&B^j_{1,2}\\ B^j_{2,1}&B^j_{2,2}\end{bmatrix}\begin{bmatrix}A^{i-1}_{1,1}&A^{i-1}_{1,2}\\ A^{i-1}_{2,1}&A^{i-1}_{2,2}\end{bmatrix}\begin{bmatrix}a\\ 0\end{bmatrix}\)

即:\(f(i+1,i)=(B^j_{1,1}A^{i-1}_{1,1}+B^j_{1,2}A^{i-1}_{2,1})\cdot a\)

代入得:

\[\begin{aligned} \sum\limits_{i=1}^n\sum\limits_{j=1}^n\binom{i+j}{i}f(i+j,i)&=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\binom{i+j}{i}(B^j_{1,1}A^{i-1}_{1,1}+B^j_{1,2}A^{i-1}_{2,1})\cdot a\\ &=a\sum\limits_{i=1}^n\sum\limits_{j=1}^n\frac{(i+j)!}{i!j!}(B^j_{1,1}A^{i-1}_{1,1}+B^j_{1,2}A^{i-1}_{2,1})\\ \end{aligned} \]

此时预处理出\(A,B\)矩阵的幂次之后就可以使用\(ntt\)计算,但需要比较优秀的常数

下面的代码是正确的,但因为常数T掉了

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
struct Matrix
{
	int w[2][2];
	void init(int a=0,int b=0,int c=0,int d=0){w[0][0]=a,w[0][1]=b,w[1][0]=c,w[1][1]=d;}
	Matrix operator * (const Matrix &t)
	{
		static Matrix res;res.init();
		rep(i,0,1) rep(j,0,1) rep(k,0,1)
			inc(res.w[i][j],mul(w[i][k],t.w[k][j]));
		return res;
	}
}pw1[MAXN],pw2[MAXN],k1,k2,one;
int n,a,b,c,d,e,ans;
int A[MAXN<<1],B[MAXN<<1],fac[MAXN],ifac[MAXN];
int rev[MAXN<<1],lim,lg,pw[30],ipw[30];
int q_pow(int bas,int t,int res=1)
{
    for(;t;t>>=1,bas=mul(bas,bas)) if(t&1) res=mul(res,bas);return res;
}
#define inv(x) q_pow(x,MOD-2)
void ntt(int *a,int n,int f)
{
    rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(int i=1,t=1;i<n;i<<=1,++t)
    {
        int wn= f>0?pw[t]:ipw[t];for(int j=0;j<n;j+=i<<1)
        {
            int w=1,x,y;for(int k=0;k<i;++k,w=mul(w,wn))
                x=a[j+k],y=mul(a[j+k+i],w),a[j+k]=pls(x,y),a[j+k+i]=mns(x,y);
        }
    }
    if(f>0) return ;int nv=inv(n);rep(i,0,n-1) a[i]=mul(a[i],nv);
}
int main()
{
	one.init(1,0,0,1);pw1[0]=pw2[0]=one,ans=0;
	fac[0]=ifac[0]=1;rep(i,1,2e5) fac[i]=mul(fac[i-1],i),ifac[i]=inv(fac[i]);
	rep(T,1,read())
	{
		n=read(),a=read(),b=read(),c=read(),d=read(),e=read();
		k1.init(b,c,1,0);k2.init(d,e,1,0);ans=0;
		rep(i,1,n) pw1[i]=pw1[i-1]*k1,pw2[i]=pw2[i-1]*k2;
	    for(lim=1,lg=1;lim<(n+1<<1);lim<<=1,lg++)
	        pw[lg]=q_pow(3,(MOD-1)/(1<<lg)),ipw[lg]=inv(pw[lg]);
	    rep(i,1,lim-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<lg-2);
	    rep(i,1,n) A[i]=mul(pw1[i-1].w[0][0],ifac[i]);
	    rep(i,1,n) B[i]=mul(pw2[i].w[0][0],ifac[i]);
	    B[0]=0;rep(i,n+1,lim-1) A[i]=B[i]=0;
	    ntt(A,lim,1);ntt(B,lim,1);rep(i,0,lim-1) A[i]=mul(A[i],B[i]);ntt(A,lim,-1);
	    rep(i,0,2*n) tms(A[i],fac[i]),inc(ans,A[i]);
	    rep(i,1,n) A[i]=mul(pw1[i-1].w[1][0],ifac[i]);
	    rep(i,1,n) B[i]=mul(pw2[i].w[0][1],ifac[i]);
	    B[0]=0;rep(i,n+1,lim-1) A[i]=B[i]=0;
	    ntt(A,lim,1);ntt(B,lim,1);rep(i,0,lim-1) A[i]=mul(A[i],B[i]);ntt(A,lim,-1);
	    rep(i,0,2*n) tms(A[i],fac[i]),inc(ans,A[i]);
	    
	    tms(ans,a);
	    printf("%d\n",ans);
	}
}

考虑一个线性递推的过程,令矩阵\(F_j=\sum\limits_{i=1}^n\binom{i+j}{i}B^jA^{i-1}\),则最终答案为\(\sum\limits_{j=1}^nF_j\begin{bmatrix}a\\0\end{bmatrix}\)

而:

\[\begin{aligned} F_{j+1}&=\sum\limits_{i=1}^n\binom{i+j+1}{i}B^{j+1}A^{i-1}\\ &=\sum\limits_{i=1}^n\left[\binom{i+j}{i}+\binom{i+j}{i-1}\right]B^{j+1}A^{i-1}\\ &=B\sum\limits_{i=1}^n\binom{i+j}{i}B^jA^{i-1}+\sum\limits_{i=1}^n\binom{i+j}{i-1}B^{j+1}A^{i-1}\\ &=BF_j+\sum\limits_{i=0}^{n-1}\binom{i+j+1}{i}B^{j+1}A^i\\ &=BF_j+\sum\limits_{i=1}^n\binom{i+j+1}{i}B^{j+1}A^i+B^{j+1}A^0-\binom{n+j+1}{n}B^{j+1}A^n\\ &=BF_j+\left[\sum\limits_{i=1}^n\binom{i+j+1}{i}B^{j+1}A^{i-1}\right]A+B^{j+1}-\binom{n+j+1}{n}B^{j+1}A^n\\ &=BF_j+F_{j+1}A+B^{j+1}-\binom{n+j+1}{n}B^{j+1}A^n\\ \end{aligned} \]

移项得:

\[F_{j+1}(I-A)=BF_j+B^{j+1}-\binom{n+j+1}{n}B^{j+1}A^n \]

由于\(I-A=\begin{bmatrix}1-b&-c\\-1&1\end{bmatrix}\) 一定满秩,其逆矩阵一定存在,\((I-A)^{-1}=\frac{1}{1-b-c}\begin{bmatrix}1&c\\1&1-b\end{bmatrix}\)

则:

\[F_{j+1}=\left[BF_j+B^{j+1}-\binom{n+j+1}{n}B^{j+1}A^n\right](I-A)^{-1} \]

由此即可在\(O(\omega^3)\)的复杂度内递推得到\(F_{j+1}\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
struct Matrix
{
	int w[2][2];
	void init(int a=0,int b=0,int c=0,int d=0){w[0][0]=a,w[0][1]=b,w[1][0]=c,w[1][1]=d;}
	Matrix operator * (const Matrix &t)
	{
		static Matrix res;res.init();
		rep(i,0,1) rep(j,0,1) rep(k,0,1)
			inc(res.w[i][j],mul(w[i][k],t.w[k][j]));
		return res;
	}
	Matrix operator + (const Matrix &t)
	{
		static Matrix res;res.init();
		rep(i,0,1) rep(j,0,1)
			res.w[i][j]=pls(w[i][j],t.w[i][j]);
		return res;
	}
	Matrix operator - (const Matrix &t)
	{
		static Matrix res;res.init();
		rep(i,0,1) rep(j,0,1)
			res.w[i][j]=mns(w[i][j],t.w[i][j]);
		return res;
	}
	Matrix operator * (const int &t)
	{
		static Matrix res;
		rep(i,0,1) rep(j,0,1) res.w[i][j]=mul(w[i][j],t);
		return res;
	}
}pw1[MAXN],pw2[MAXN],k1,k2,one,invm,res;
int n,a,b,c,d,e,fac[MAXN],ifac[MAXN],ans;
inline int C(int n,int m)
{
	if(n<0||n<m) return 0;
	return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main()
{
	one.init(1,0,0,1);pw1[0]=pw2[0]=one,ans=0;fac[0]=ifac[0]=1;
	rep(i,1,2e5) fac[i]=mul(fac[i-1],i),ifac[i]=Inv(fac[i]);
	rep(T,1,read())
	{
		n=read(),a=read(),b=read(),c=read(),d=read(),e=read();
		k1.init(b,c,1,0);k2.init(d,e,1,0);ans=0;res.init();
		invm.init(1,c,1,mns(1,b));invm=invm*Inv(mns(1,b+c));
		rep(i,1,n) pw1[i]=pw1[i-1]*k1,pw2[i]=pw2[i-1]*k2;
		rep(i,1,n) res=res+pw2[1]*pw1[i-1]*(i+1);
		inc(ans,res.w[0][0]);
		rep(i,2,n)
		{
			res=(k2*res+pw2[i]-pw2[i]*pw1[n]*C(n+i,n))*invm;
			inc(ans,res.w[0][0]);
		}
	    tms(ans,a);
	    printf("%d\n",ans);
	}
}

F

注意到\((x-2)^2+(x+1)^2-(x-1)^2-x^2=4\)

因此我们可以构造出\(1,2,3,4\)的方案后直接在串后添加若干个\(1001\)即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,lim=1e6;
char s[MAXN];
int main()
{
	rep(i,1,lim) s[i]='1',s[i+1]='0',s[i+2]='0',s[i+3]='1',i=i+3;
	rep(T,1,read())
	{
		scanf("%d",&n);
		if(n%4==1) printf("%d\n1",n);
		else if(n%4==2) printf("%d\n0001",n+2);
		else if(n%4==3) printf("%d\n01",n-1);
		else printf("%d\n",n);
		n=(n/4)*4;
		printf("%s",s+lim-n+1);puts("");
	}
}

G

对于\(g(x)\)相同的数,函数为关于\(x\)的二次函数,而\(g(x)\)的取值很小

因此预处理出每个\(g(x)\)的所有\(x\),每次三分求出这个\(g(x)\)的最小值

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
ll n,a,b,c,d;
const ll inf=1e18;
ll res,ans;
vector<int> g[60];
inline int calc(int x,int res=0){while(x) res+=x%10,x/=10;return res;}
inline ll getw(ll x,ll y){return a*x*x*y+b*x*x+c*x*y*y+d*x*y;}
void mem(int n=1e6) {rep(i,1,n) g[calc(i)].pb(i);}
int main()
{
	mem();int l,r,ml,mr;ll al,ar;
	rep(T,1,read())
	{
		a=read(),b=read(),c=read(),d=read(),n=read();ans=inf;
		rep(i,1,54)
		{
			res=inf;l=0,r=upper_bound(g[i].begin(),g[i].end(),n)-g[i].begin()-1;
			for(;l<r;)
			{
				ml=l+r>>1;mr=ml+1;
				al=getw(g[i][ml],i),ar=getw(g[i][mr],i);
				res=min(res,min(al,ar));
				if(al<ar) r=mr-1;else l=ml+1;
			}
			if(l==r) res=min(res,getw(g[i][l],i));
			ans=min(ans,res);
		}
		printf("%lld\n",ans);
	}
}

H

考虑枚举\(gcd\),每次在数列中找到\(gcd\)的所有倍数,令排序后这些数的位置数组为\(pos\)

则满足\(l\le p_i,r\ge p_{i+1},1\le i< \lfloor\frac{n}{g}\rfloor\)的所有区间\([l,r]\)答案至少为\(g\)

因此可以倒着枚举\(gcd\),每次第一个被修改的\([l,r]\)答案即为\(g\)

考虑用线段树维护每个\(l\)被修改过的\(r\)最小值

直接做的话显然需要维护区间和并支持区间取\(min\)操作,似乎需要\(segment\ tree\ beats!\)

但实际并不需要,由于每次修改的\(l,r\)都是单增的,因此整个线段树维护的值也一定是单调的

可以再维护区间最大值,每次在线段树上二分出需要被修改的区间,线段树只需要支持区间赋值,区间求和即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
int n,g[MAXN],p[MAXN],pos[MAXN],m;
int tag[MAXN<<2],mx[MAXN<<2];
ll sum[MAXN<<2],ans[MAXN];
inline void Mdf(int k,int l,int r,int w)
{
	tag[k]=w,sum[k]=1LL*(r-l+1)*w,mx[k]=w;
}
inline void pshd(int k,int l,int r,int mid)
{
	Mdf(k<<1,l,mid,tag[k]);Mdf(k<<1|1,mid+1,r,tag[k]);
	tag[k]=0;
}
inline void upd(int k)
{
	sum[k]=sum[k<<1]+sum[k<<1|1], 
	mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
void build(int k,int l,int r)
{
	tag[k]=0;if(l==r) {sum[k]=mx[k]=n+1;return ;}
	int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	upd(k);
}
void mdf(int k,int l,int r,int a,int b,int w)
{
	if(a<=l&&r<=b) {Mdf(k,l,r,w);return ;}
	int mid=l+r>>1;if(tag[k]) pshd(k,l,r,mid);
	if(a<=mid) mdf(k<<1,l,mid,a,b,w);
	if(b>mid) mdf(k<<1|1,mid+1,r,a,b,w);
	upd(k);
}
int find(int k,int l,int r,int x)
{
	if(l==r) return sum[k]>x?l:n+1;int mid=l+r>>1;
	if(tag[k]) pshd(k,l,r,mid);
	return mx[k<<1]<=x?find(k<<1|1,mid+1,r,x):find(k<<1,l,mid,x);
}
ll query(int k,int l,int r,int a,int b)
{
	if(a<=l&&r<=b) return sum[k];int mid=l+r>>1;ll res=0;
	if(tag[k]) pshd(k,l,r,mid);
	if(a<=mid) res+=query(k<<1,l,mid,a,b);
	if(b>mid) res+=query(k<<1|1,mid+1,r,a,b);
	return res;
}
int main()
{
	int l,r;rep(T,1,read())
	{
		n=read();
		rep(i,1,n) g[i]=read(),pos[g[i]]=i,ans[i]=0;
		build(1,1,n);
		dwn(i,n/2,2)
		{
			m=0;for(int j=i;j<=n;j+=i) p[++m]=pos[j];
			sort(p+1,p+m+1);
			rep(j,1,m-1)
			{
				r=p[j],l=find(1,1,n,p[j+1]);
				if(l>r) continue;
				ans[i]+=query(1,1,n,l,r)-1LL*p[j+1]*(r-l+1);
				mdf(1,1,n,l,r,p[j+1]);
			}
		}
		ans[1]=1LL*n*(n-1)/2;
		rep(i,2,n) ans[1]-=ans[i];
		rep(i,1,n) printf("%lld\n",ans[i]);
	}
}

I

签到题,\(map\)记录每个\(pair\)的出现次数

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
int n;char s[MAXN];ll ans;
map<pii,int> m;
int main()
{
	int x,y;rep(T,1,read())
	{
		n=read();scanf("%s",s+1);
		m.clear();x=y=0;m[{0,0}]=1;ans=0;
		rep(i,1,n)
		{
			if(s[i]=='U') y++;if(s[i]=='D') y--;
			if(s[i]=='R') x++;if(s[i]=='L') x--;
			ans+=m[{x,y}];m[{x,y}]++;
		}
		printf("%lld\n",ans);
	}
}

K

可以先预处理每一列净消耗若干个子弹获得的最大代价,基本转化为了普通背包

问题在于无论怎么选择,最后一颗子弹打完之后就不能继续获得当前局面下净花费为\(0\)的价值了

因此我们\(dp\)多一维\(0/1\),表示是否有选择某一个物品为结束时的花费

转移依然很简单,最终答案全部打完子弹且有选择结束的\(dp\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
char ch[5];
int n,m,k,f[220][220][2],w[220][220],ed[220][220];
int a[220][220],ok[220][220],mx[220],lft[220];
int main()
{
	rep(T,1,read())
	{
		n=read(),m=read(),k=read();
		rep(i,1,n) rep(j,1,m)
		{
			scanf("%d%s",&a[i][j],ch);ok[i][j]=(ch[0]=='Y')?1:0;
		}
		rep(j,1,m)
		{
			w[j][mx[j]=0]=0;
			dwn(i,n,1)
			{
				if(!ok[i][j]) w[j][mx[j]+1]=w[j][mx[j]],mx[j]++,ed[j][mx[j]]=w[j][mx[j]]+a[i][j];
				w[j][mx[j]]+=a[i][j];
			}
		}
		rep(i,0,m) rep(j,0,k) f[i][j][0]=f[i][j][1]=-inf;f[0][k][0]=0;
		rep(i,1,m) rep(j,0,k) 
		{
			f[i][j][1]=f[i-1][j][1]+w[i][0];
			if(j) f[i][j][0]=f[i-1][j][0]+w[i][0];
			else f[i][j][0]=f[i-1][j][0];
			rep(l,1,min(mx[i],k-j))
			{
				f[i][j][0]=max(f[i][j][0],f[i-1][j+l][0]+w[i][l]),
				f[i][j][1]=max(f[i][j][1],f[i-1][j+l][0]+ed[i][l]),
				f[i][j][1]=max(f[i][j][1],f[i-1][j+l][1]+w[i][l]);
			}
		}
		printf("%d\n",f[m][0][1]);
	}
}

L

因为答案是单增的,所以对于数\(x\),需要找到最前面的点来转移即找到一个\(p\)使\(x-x\ mod \ p\)最小

我们可以开一个小根堆来记录每个质数当前的倍数,每次找到符合条件的最小值转移

如果该质数对应的倍数过小则用本次的\(x\)来更新,每一个质数至多被\(pop\ \lceil\frac{N}{p}\rceil\)

因此复杂度为\(O(N\log P+P \log P\log\log n)\)可以通过

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 2001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
struct Data{int w,pos;}res;
bool operator < (Data x,Data y){return x.pos>y.pos;}
priority_queue<Data> q;
int N,m,n,p[MAXN],ans[MAXN];
ull pw[MAXN],sum;ll lcm;
int main()
{
	pw[0]=1;rep(i,1,2e6) pw[i]=pw[i-1]*23333;
	rep(T,1,read())
	{
		N=m=read(),n=read();sum=0,lcm=1;
		rep(i,1,n) {p[i]=read();q.push({p[i],0});if(lcm-1<m) lcm*=p[i];}
		if(lcm-1<m) m=lcm-1;
		rep(i,1,m)
		{
			for(res=q.top();i/res.w*res.w!=res.pos;res=q.top())
				{q.pop();res.pos=i/res.w*res.w;q.push(res);}
			ans[i]=ans[res.pos]+1,sum+=pw[N-i]*ans[i];
		}
		printf("%llu\n",sum);
		while(!q.empty()) q.pop();
	}
}
posted @ 2021-09-03 16:53  jack_yyc  阅读(75)  评论(0编辑  收藏  举报