1003
手玩一下发现如果是一维的只能有两个,二维的只能有三个。
所以得出结论,一维能分开一个。
code:
int T;ll n,k; int main(){ scanf("%d",&T);while(T--) scanf("%lld%lld",&n,&k),puts(n<=k+1?"Yes":"No"); }
1004
考虑枚举两个串的开头位置,那么可以通过尺取\(O(n^2)\)得到所有的右端点。
得到右端点后发现是个区间加等差数列的东西。
这个东西直接二阶差分就完事了。
code:
using namespace std; int T,n,k,len,r,cnt;char S[N+5];ll Q[N+5<<1],Sum[N+5<<1]; I void Solve(){ re int i,j;scanf("%d%d",&n,&k);scanf("%s",S+1);Me(Q,0);Me(Sum,0); for(i=1;i<n;i++){ for(cnt=r=0,j=1;j<=n-i;j++){ if(j^1)cnt-=(S[j-1]!=S[j+i-1]);while(r+i<=n&&cnt<=k) r++,cnt+=(S[r]!=S[r+i]);//printf("%d %d %d\n",j,r,i); if(r>j+i)Sum[j]++,Sum[j+i]--,Sum[j+i]-=i,Sum[j+i+1]+=i; else Sum[j]++,Sum[r]--,Sum[j+i]-=r-j,Sum[j+i+1]+=r-j; } } for(i=1;i<=n;i++) Sum[i]+=Sum[i-1];for(i=1;i<n;i++) Sum[i]+=Sum[i-1],printf("%lld\n",Sum[i]); } int main(){ freopen("1.in","r",stdin); scanf("%d",&T);while(T--) Solve(); }
1006
代码都给你了,直接模拟。
code:
using namespace std; int T;ll n,m,Ans,tot,pus,ToT1,ToT2,ToT3,ToT4; I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const ll inv2=mpow(2),inv6=mpow(6); I void Solve(){ scanf("%lld",&n);m=n%mod;ToT1=(m+1)*m%mod*inv2%mod;ToT2=m*(m+1)%mod*(2*m+1)%mod*inv6%mod; printf("%lld\n%lld\n",((ToT1*ToT2*2+ToT1*ToT1-ToT1-ToT1-ToT2+1-ToT1+1)%mod+mod)%mod,m*ToT1%mod*ToT2%mod*m%mod); } int main(){ freopen("1.in","r",stdin); scanf("%d",&T);while(T--) Solve(); }
1007
出题人的英语水平真的可以。
考虑最多就是全放完,最少就是分别在\(x|y|z=1\)的地方放。
注意\(x=y=1\)那一列只留最底下那个就好了。
code:
int T;ll n,m,Ans,tot,pus,ToT1,ToT2,ToT3,ToT4; I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const ll inv2=mpow(2),inv6=mpow(6); I void Solve(){ scanf("%lld",&n);m=n%mod;ToT1=(m+1)*m%mod*inv2%mod;ToT2=m*(m+1)%mod*(2*m+1)%mod*inv6%mod; printf("%lld\n%lld\n",((ToT1*ToT2*2+ToT1*ToT1-ToT1-ToT1-ToT2+1-ToT1+1)%mod+mod)%mod,m*ToT1%mod*ToT2%mod*m%mod); } int main(){ freopen("1.in","r",stdin); scanf("%d",&T);while(T--) Solve(); }
1008
首先容易想到枚举每个中间的点算贡献。
他下面的节点就是他二进制下一的个数的二次幂。
然后对于每个点我们找到包含它有几个点,有多少个点通过包含它的点上来,除一下就好了。
这个过程可以FWT做。时间复杂度\(O(2^nn)\)
code:
int n,m,k,T,x,G[N+5],inv[N+5],now;ll Ans,F[N+5],W1[N+5],W2[N+5]; I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;} I void AND(ll *f) { for (int o = 2, k = 1; o <= (1<<n); o <<= 1, k <<= 1) for (int i = 0; i < (1<<n); i += o) for (int j = 0; j < k; j++) f[i+j]=(f[i+j]+f[i+j+k])%mod; } I void Solve(){ re int i;Me(F,0);Me(W1,0);Me(W2,0);scanf("%d%d",&n,&m);while(m--) scanf("%d",&x),F[x]++; for(i=0;i<(1<<n);i++) W1[i]=1ll*G[i]*F[i],W2[i]=F[i]; AND(W1);AND(W2);for(Ans=i=0;i<(1<<n);i++) Ans+=W1[i]*mpow(W2[i])%mod;printf("%lld\n",Ans%mod); } int main(){ freopen("1.in","r",stdin); re int i;for(i=0;i<N;i++){now=i;G[i]=1;while(now) G[i]<<=1,now-=now&-now;}scanf("%d",&T);while(T--) Solve(); }
1009
一个小常数\(O(nlogn)\)的,并不知道\(O(n)\)怎么做。
考虑枚举每种权值,然后将这些权值的位置设为1,其它设为-1,那么就是找权值和为正的子区间数。
因为每次只有加一减一,所以可行的起始点和结束点总共最多\(O(n)\)个。
那么直接树状数组维护就好了。
code:
using namespace std; int n,m,T,r,l,st[N+5],sh,A[N+5],Maxn,B[N+5],C[N+5],Ch,D[N+5],Dh,Fl[N+5],cnt,ToT,L[N+5],R[N+5],F[N+5<<1],Q[N+5];vector<int> G[N+5];ll Ans; I void insert(int x){while(x<=n*2) F[x]++,x+=x&-x;} I int find(int x){int ans=0;while(x)ans+=F[x],x-=x&-x;return ans;} I void clear(int x){while(x<=n*2&&F[x]) F[x]=0,x+=x&-x;;} I void Solve(){ Ans=0;re int i,j,h;scanf("%d",&n);for(i=0;i<=Maxn;i++) G[i].clear();Maxn=0;for(i=1;i<=n;i++) scanf("%d",&A[i]),G[A[i]].push_back(i),Maxn=max(Maxn,A[i]); for(j=0;j<=Maxn;j++){//printf("%d\n",j); m=G[j].size();for(i=0;i<m;i++) B[i+1]=G[j][i],Fl[B[i+1]]=1; Ch=Dh=0;for(i=1;i<=m;i++) { L[B[i]]=B[i]-1;while(L[B[i]]&&Fl[L[B[i]]])L[B[i]]=max(L[L[B[i]]]-1,0);L[B[i]]&&(C[++Ch]=L[B[i]]);C[++Ch]=B[i]; }sort(C+1,C+Ch+1); for(i=m;i;i--) { R[B[i]]=B[i]+1;while(R[B[i]]<=n&&Fl[R[B[i]]]) R[B[i]]=min(R[R[B[i]]]+1,n+1);R[B[i]]<=n&&(D[++Dh]=R[B[i]]);D[++Dh]=B[i]; }sort(D+1,D+Dh+1); for(cnt=ToT=sh=0,l=m-1,r=i=1;i<=Dh;i++){ while(r<=Ch&&C[r]<=D[i]) insert(2*cnt-C[r]+1+n),st[++sh]=2*cnt-C[r]+1+n,r++;cnt+=Fl[D[i]];Q[D[i]]=2*cnt-D[i]; Ans+=find(Q[D[i]]+n-1); } for(i=1;i<=Dh;i++) Q[D[i]]=0;for(i=1;i<=m;i++) L[B[i]]=R[B[i]]=Fl[B[i]]=0;for(i=1;i<=sh;i++) clear(st[i]); }printf("%lld\n",Ans); } int main(){ freopen("1.in","r",stdin); scanf("%d",&T);while(T--) Solve(); }