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();
}
