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\)
代入得:
此时预处理出\(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}\)
而:
移项得:
由于\(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}\)
则:
由此即可在\(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();
}
}