传送门

\(CHNUM\)

显然正数一组,负数一组

for(int T=read();T;--T){
n=read(),c=d=0;
fp(i,1,n)x=read(),x>0?++c:++d;
if(!c)c=d;if(!d)d=c;
if(c<d)c^=d^=c^=d;
printf("%d %d\n",c,d);
}

\(CHDIGER\)

从原来的数列中选出字典序最小的上升子序列,往后面加\(d\)就行了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inline __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char s[25];int t[25],d,top,n,pos,mn;
int main(){
// freopen("testdata.in","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%s%d",s+1,&d),top=0,n=strlen(s+1);
pos=1;
while(pos<=n){
mn=10;
fp(i,pos,n)if(s[i]-'0'<mn)mn=s[i]-'0',pos=i+1;
t[++top]=mn;
}
while(top&&t[top]>d)--top;
while(top<n)t[++top]=d;
fp(i,1,n)putchar(t[i]+'0');
putchar('\n');
}
return 0;
}

\(JAIN\)

压成一个\(5\)位的二进制数,高位前缀和然后乱搞就可以了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inline __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
int read(char *s){
R int len=0;R char ch;while(((ch=getc())>'z'||ch<'a'));
for(s[++len]=ch;(ch=getc())>='a'&&ch<='z';s[++len]=ch);
return s[len+1]='\0',len;
}
const int N=1e5+5;
char s[1005];int n,m,v,sum[35],p[35];ll res;
int main(){
// freopen("testdata.in","r",stdin);
for(int T=read();T;--T){
n=read(),res=0;
fp(i,0,31)sum[i]=p[i]=0;
fp(i,1,n){
m=read(s),v=0;
fp(j,1,m){
v|=(s[j]=='a'),
v|=(s[j]=='e')<<1,
v|=(s[j]=='i')<<2,
v|=(s[j]=='o')<<3,
v|=(s[j]=='u')<<4;
}
++sum[v];
}
fp(i,0,31)p[i]=sum[i];
fp(j,0,4)fp(i,0,31)if(i>>j&1)p[i^(1<<j)]+=p[i];
fp(i,1,30)res+=sum[i]*p[31^i];
res+=1ll*sum[31]*(n-1);
printf("%lld\n",res>>1);
}
return 0;
}

\(SUBPRNJL\)

显然有\(m=\left\lceil{k\over r-l+1}\right\rceil\),以及选中的数字是\([l,r]\)中\(sort\)之后的第\(\left\lceil{k\over m}\right\rceil\)个数。区间第\(k\)小可以记录一下前缀和之后二分

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=2005;
int sz[N][N],sum[N][N],n,k,x,m,res;
int find(int bl,int br,int k){
int l=1,r=2000,ans=0,mid;
while(l<=r){
mid=(l+r)>>1;
sum[br][mid]-sum[bl-1][mid]>=k?(ans=mid,r=mid-1):l=mid+1;
}
return ans;
}
int main(){
// freopen("testdata.in","r",stdin);
for(int T=read();T;--T){
n=read(),k=read(),res=0;
fp(i,1,n){
memset(sum[i],0,(n+1)<<2);
memset(sz[i],0,(n+1)<<2);
x=read(),sz[i][x]=1;
fp(j,1,2000)sz[i][j]+=sz[i-1][j];
fp(j,1,2000)sum[i][j]=sum[i][j-1]+sz[i][j];
}
fp(l,1,n)fp(r,l,n){
m=(k+r-l)/(r-l+1),x=(k+m-1)/m;
x=find(l,r,x),x=sz[r][x]-sz[l-1][x];
if(sz[r][x]-sz[l-1][x])++res;
}
printf("%d\n",res);
}
return 0;
}

\(CHONQ\)

因为形如\(\left\lfloor{n\over i}\right\rfloor\)的取值只有\(O(\sqrt{n})\)种,我们可以直接整除分块来预处理一下贡献

然而不知道为何我的整除分块\(T\)掉了……我的暴力交上去却\(A\)了……

还是换种写法吧,我们把\(i\)左边前\(\sqrt{a_i}\)个数暴力加上贡献,后面的用类似前缀和的办法在分界点预处理贡献。最后把前缀和加起来就好了

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1e5+5;
int a[N],d[N][317],c[N],lst[N],n,k,res,pos;
int main(){
// freopen("testdata.in","r",stdin);
fp(i,1,100000)fp(j,1,sqrt(i))d[i][j]=i/j;
fp(i,1,100000)lst[i]=sqrt(i);
for(int T=read();T;--T){
n=read(),k=read();
fp(i,1,n)a[i]=read(),c[i]=0;
fp(i,1,n){
for(R int j=1,pos;j<=lst[a[i]];++j){
pos=max(1,i-d[a[i]][j]+1);
c[pos]-=j-1,c[pos]+=j;
}
int j=lst[a[i]],pos=max(1,i-j+1);
c[pos]-=j,c[pos]+=d[a[i]][j];
for(R int j=lst[a[i]]-1,pos;j;--j){
pos=max(1,i-j+1);
c[pos]-=d[a[i]][j+1],c[pos]+=d[a[i]][j];
}
c[i+1]-=a[i];
}
res=0,pos=n+1;
fp(i,1,n){
res+=c[i];
if(res<=k){pos=i;break;}
}
printf("%d\n",pos);
}
return 0;
}

\(CHEFSOC\)

我永远讨厌\(dp.jpg\)

我们设\(f_{i,0/1}\)表示从前面跳过来,\(0/1\)表示\(i-1\)是否被跳到过,的方案数,转移的话可以看代码,比较显然

然后还有一个问题是它可能从后面跳过来……这种情况肯定是先跳到\(i+1\),然后在后面经历了一番不可描述的事情之后跳回了\(i\)。我们设\(g_i\)表示从\(i+1\)跳回到\(i\)的方案,这个转移也看代码好了……

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1e5+5,P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int f[N][2],g[N],a[N],res,n;
int main(){
// freopen("testdata.in","r",stdin);
for(int T=read();T;--T){
n=read(),res=0;
fp(i,1,n)a[i]=read();
f[1][0]=1,f[1][1]=0;
fp(i,2,n){
f[i][1]=add(f[i-1][0],f[i-1][1]),f[i][0]=0;
if(a[i-2]==2)f[i][0]=add(f[i-2][0],f[i-2][1]),upd(f[i][1],f[i-1][0]);
}
g[n]=g[n+1]=0,res=add(f[n][0],f[n][1]);
fd(i,n-1,1){
upd(res,add(f[i][0],f[i][1])),g[i]=1;
if(a[i+1]==2&&a[i+2]==2)upd(g[i],g[i+2]);
if(a[i+2]==2)++g[i];
upd(res,mul(f[i+1][0],g[i]));
}
printf("%d\n",res);
}
return 0;
}

\(PTREE\)

没有题解的代码食用体验极差……

用了一个晚上看懂代码,又用了一个早上调自己的代码……

因为本题非常需要卡常,所以您最好先知道一些卡常用的小\(trick\)

\(O(1)\)快速幂

简单来说我们需要在给定\(x\)的情况下多次求\(x^i\)

我们可以令\(s=\sqrt{P}\),预处理出\(x^0,x^1,...,x^s\),以及\(x^0,x^s,x^{2s},...\),然后就可以\(O(1)\)查询了

不过本题中最大只需要查到\(x^n\),所以这里我们令\(s=\sqrt{n}\)就可以了

等比数列求和

如果要计算形如\(\sum\limits_{i=0}^{k-1}p^i\),可以直接用等比数列求和公式代入计算\({1-p^k\over1-p}\),复杂度\(O(\log P)\)(求逆元)

或者把长为\(k\)的数列拆成\(\log k\)段计算,复杂度\(O(\log k)\)

int calc(R int x,R int y){
R int res=1,d=1;
for(--y;y;y>>=1,d=add(mul(d,x),d),x=mul(x,x))(y&1)?res=add(mul(res,x),d):0;
return res;
}

题解

因为这是一个完美树,所以显然深度为\(k\)的点数大于等于深度为\(k-1\)的点数

我们定义一个深度\(k\)为特殊的,当且仅当深度为\(k\)的点数大于深度为\(k-1\)的点数。不难发现特殊深度的个数是\(O(\sqrt{n})\)的

对于任何一棵子树来说,第\(i\)个特殊深度和第\(i-1\)个特殊深度之间所有深度的点数都相同

我们找出所有的特殊深度,并将它们的值离散化,然后再做一个前缀和,令\(sm[i][j]\)表示\(1\)到\(i\)之间深度为\(j\)的点数有多少个(这里的深度是离散化之后的特殊深度),\(i\)表示的是\(dfs\)序。那么我们就可以用前缀和相减的形式来求出一棵子树内某个特定深度的点数了

然后我们再设一个\(nxt[k]\),表示\(k\)之后的下一个特殊深度是什么(这里的深度是没有离散化过的)。对于询问\((u,x)\),我们从\(dep[u]\)开始不断跳\(nxt\),根据性质跳的次数是\(O(\sqrt{n})\)的

那么设当前子树内\([l,r-1]\)之间的所有深度的点数都相同,设为\(k\),且深度为\([dep[u],l-1]\)之间的点数共有\(s\)个,令\(d=dep[u]\),我们需要快速处理贡献

很容易写出一个暴力,贡献即为

\[Ans=\sum_{i=l}^{r-1}x^{sum+(i-l)k}(i-d)\sum_{j=0}^{k-1}x^j
\]

如果直接暴力处理贡献的话,虽然后面等比数列求和可以用之前说的\(O(\log k)\)搞,但是前面显然是\(O(n)\)的……肯定\(gg\)啊……

鉴于代码里原本写的东西我实在看不太懂,所以换了一种方式

那就开始推倒吧

\[\begin{aligned}
Ans
&=\sum_{i=l}^{r-1}x^{sum+(i-l)k}(i-d)\sum_{j=0}^{k-1}x^j\\
&=\sum_{i=l}^{r-1}x^{sum+(i-l)k}(i-d){x^k-1\over x-1}\\
&={x^{sum}\over x-1}\sum_{i=l}^{r-1}x^{(i-l)k}(i-d)(x^k-1)
\end{aligned}
\]

令\(p=x^k\),并忽略\(\sum\)前面的那些常数

\[\begin{aligned}
Ans
&=\sum_{i=l}^{r-1}p^{i-l}(i-d)(p-1)\\
&=\sum_{i=l}^{r-1}p^{i-l}i(p-1)-\sum_{i=l}^{r-1}p^{i-l}d(p-1)
\end{aligned}
\]

对于后面,可以化成

\[\begin{aligned}
\sum_{i=l}^{r-1}p^{i-l}d(p-1)
&=d(p-1)\sum_{i=0}^{r-l-1}p^i\\
\end{aligned}
\]

后面就是个等比数列求和的形式,按上面说的搞就行了

对于前面,有

\[\begin{aligned}
\sum_{i=l}^{r-1}p^{i-l}i(p-1)
&=(p-1)\sum_{i=0}^{r-l-1}p^i(i+l)\\
&=(p-1)\sum_{i=0}^{r-l-1}p^ii+(p-1)l\sum_{i=0}^{r-l-1}p^i
\end{aligned}
\]

后面还是个等比数列求和的形式,关键是前面

简单来说,我们需要对一个形如

\[\sum_{i=0}^{n-1}p^i\times i
\]

的东西求和

这就是个等比\(+\)等差数列的求和,根据高中数学必修五的芝士,可得它等于

\[{p^n(n-1)-\sum_{i=1}^{n-1}p^i\over p-1}
\]

分母里,前面的快速幂我们已经预处理过了,后面又是个等比数列求和,老办法搞

然后没有然后了,细节可以看代码

一道树据结构题被我硬生生做成了数学题

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=5e5+5,L=455,P=1e9+7;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
int gsum(R int x,R int y){
if(!y)return 0;
R int res=1,d=1;
for(--y;y;y>>=1,d=add(mul(d,x),d),x=mul(x,x))(y&1)?res=add(mul(res,x),d):0;
return res;
}
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int sz[N],dfn[N],rs[N],sm[N][1005],bin[L+5],bp[L+5],id[N],nxt[N],dep[N],sum[N];
int fi[N],se[N];
int n,m,cnt,t,D,lasans;
void dfs(int u,int fa){
++sz[dep[u]=dep[fa]+1],dfn[u]=++cnt,sum[u]=dep[u];
go(u)if(v!=fa)dfs(v,u),sum[u]=add(sum[u],sum[v]);
rs[u]=cnt;
}
void clr(){
memset(head,0,(n+1)<<2);
memset(sz,0,(n+1)<<2);
fp(i,1,n)memset(sm[i],0,(t+1)<<2);
}
int main(){
// freopen("testdata.in","r",stdin);
fp(i,1,N-1)fi[i]=i/L,se[i]=i%L;
for(int T=read();T;--T){
n=read(),m=read(),tot=0;
for(R int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
cnt=t=0;dfs(1,0);
D=0;fp(i,1,n)cmax(D,dep[i]);
int ls=D+1;
fp(i,1,D)if(sz[i]!=sz[i-1])id[i]=++t;
id[D+1]=t+1;
for(R int i=D,ls=D+1;i;sz[i]!=sz[i-1]?ls=i:0,--i)nxt[i]=ls;
nxt[0]=nxt[1];
for(R int i=1,h=dep[i];i<=n;++i,h=dep[i])
sz[h]!=sz[h-1]?++sm[dfn[i]][id[h]]:0;
fp(i,2,n)fp(j,1,t)sm[i][j]+=sm[i-1][j];
lasans=0;
while(m--){
int u=read(),x=read();u^=lasans,x^=lasans;
if(x==1){
print(lasans=dec(sum[u],mul(dep[u],rs[u]-dfn[u]+1)));
continue;
}
bin[0]=1;fp(i,1,L)bin[i]=mul(bin[i-1],x);
bp[0]=1;fp(i,1,L)bp[i]=mul(bp[i-1],bin[L]);
int sum=0,ans=0,*sl=sm[dfn[u]-1],*sr=sm[rs[u]];
int l=dep[u],r=nxt[l];sl+=id[r]-1,sr+=id[r]-1;
for(;l<=D;l=r,r=nxt[l]){
int num=max(1,*sr-*sl);
++sl,++sr;
while(r<=D){
int k=max(1,*sr-*sl);
if(k!=num)break;
r=nxt[r],++sl,++sr;
}
int p=mul(bp[fi[num]],bin[se[num]]),pn=mul(bp[fi[num*(r-l)]],bin[se[num*(r-l)]]);
int res=dec(mul(pn,r-l-1),mul(p,gsum(p,r-l-1)));
res=add(res,mul(l-dep[u],pn-1));
ans=add(ans,1ll*bp[fi[sum]]*bin[se[sum]]%P*res%P);
sum+=num*(r-l);
}
print(lasans=mul(ans,ksm(x-1,P-2)));
}
clr();
}
return Ot(),0;
}

\(MATPER\)

我讨厌搜索\(.jpg\)

我们先对每一个\(P_i\)都跑一遍\(kmp\),找出它在\(s\)中出现的所有位置,并预处理出\(f_{i,k}\)表示位置\(k\)之后第一个\(P_i\)结尾的位置,以及\(g_{i,k}\)表示位置\(k\)之前第一个\(P_i\)结尾的位置

然后我们\(meet-in-the-middle\)就行了

//minamoto
#include<bits/stdc++.h>
#define R register
#define pb push_back
#define ll long long
#define IT vector<int>::iterator
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
int read(char *s){
R int len=0;R char ch;while(((ch=getc())>'z'||ch<'a'));
for(s[++len]=ch;(ch=getc())>='a'&&ch<='z';s[++len]=ch);
return s[len+1]='\0',len;
}
const int N=1e5+5,M=15;
char s[N],p[M][N];int lp[M],f[M][N],g[M][N],lg[(1<<M)+5],kmp[N],sz[(1<<M)+5];
vector<int>c[N],cc[N],pos[M];int n,m,u,t;ll res;
void dfs1(int st,int ch,int ed){
if(st==t)return c[ed].pb(ch),void();
int y;
for(int x=u^ch,i=lg[x&-x]+1;x;x&=x-1,i=lg[x&-x]+1)
if(!pos[i].empty()&&pos[i].back()-lp[i]+1>ed){
y=f[i][ed+lp[i]];
if(~y)dfs1(st+1,ch|(1<<(i-1)),y);
}
}
void dfs2(int st,int ch,int op){
if(st==t+1)return cc[op].push_back(ch),void();
int y;
for(int x=u^ch,i=lg[x&-x]+1;x;x&=x-1,i=lg[x&-x]+1)
if(!pos[i].empty()&&pos[i].front()<op){
y=g[i][op];
if(~y)dfs2(st-1,ch|(1<<(i-1)),y-lp[i]+1);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),read(s);
fp(i,1,m)lp[i]=read(p[i]);
fp(k,1,m){
kmp[0]=-1;
for(R int i=1,j=0;i<=lp[k];kmp[i]=j+1,++i)
for(j=kmp[i-1];~j&&p[k][j+1]!=p[k][i];j=kmp[j]);
for(R int i=1,j=1;i<=n;++i){
while(~j&&p[k][j+1]!=s[i])j=kmp[j];
if(++j==lp[k])pos[k].pb(i);
}
fp(i,0,n+1){
IT it=lower_bound(pos[k].begin(),pos[k].end(),i);
f[k][i]=(it==pos[k].end())?-1:*it;
g[k][i]=(it==pos[k].begin())?-1:*--it;
}
}
u=(1<<m)-1;fp(i,0,m-1)lg[1<<i]=i;
t=m>>1;
dfs1(0,0,0),dfs2(m+1,0,n+1);
fd(i,n+1,0){
fp(j,0,c[i].size()-1)res+=sz[u^c[i][j]];
fp(j,0,cc[i].size()-1)++sz[cc[i][j]];
}
printf("%lld\n",res);
return 0;
}

\(TREASURE\)

把它写成若干个异或方程组,解的个数就是\(2^{自由元个数}\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=905,P=1e9+7;
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
bitset<N>a[N];int n,m;
inline int id(R int i,R int j){return (i-1)*m+j;}
int Gauss(int n,int m){
int res=m-1;
fp(i,0,n-1){
int x=a[i]._Find_first();
if(x==m)return -1;
if(x>m)continue;
--res;
fp(j,i+1,n-1)if(a[j][x])a[j]^=a[i];
}
return res;
}
int main(){
// freopen("testdata.in","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
int tot=0,mx=n*m+1,x;
fp(i,1,n)fp(j,1,m){
scanf("%d",&x);
if(x==-1)continue;
a[tot]=0;
if(i>1)a[tot][id(i-1,j)]=1;
if(j>1)a[tot][id(i,j-1)]=1;
if(i<n)a[tot][id(i+1,j)]=1;
if(j<m)a[tot][id(i,j+1)]=1;
a[tot][mx]=x,++tot;
}
int k=Gauss(tot,mx);
printf("%d\n",k<0?0:ksm(2,k));
}
return 0;
}

\(SONATR\)

代码两百多行的……咕咕……

CodeChef March Challenge 2019题解的更多相关文章

  1. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

  2. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  3. CodeChef November Challenge 2019 Division 1题解

    传送门 AFO前的最后一场CC了--好好打吧-- \(SIMGAM\) 偶数行的必定两人平分,所以只要抢奇数行中间那个就行了 这题怎么被爆破了 //quming #include<bits/st ...

  4. Codechef July Challenge 2019 Division 1题解

    题面 \(CIRMERGE\) 破环成链搞个裸的区间\(dp\)就行了 //quming #include<bits/stdc++.h> #define R register #defin ...

  5. Code Chef February Challenge 2019题解

    传送门 \(HMAPPY2\) 咕 话说这题居然卡\(scanf\)的么??? int T;cin>>T; while(T--){ cin>>n>>a>> ...

  6. Codechef March Challenge 2014——The Street

    The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...

  7. Codechef November Challenge 2019 Division 1

    Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...

  8. Codechef October Challenge 2019 Division 1

    Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...

  9. Codechef September Challenge 2019 Division 2

    Preface 这确实应该是我打过的比较水的CC了(其实就打过两场) 但由于我太弱了打的都是Div2,所以会认为上一场更简单,其实上一场Div的数据结构是真的毒 好了废话不多说快速地讲一下 A Eas ...

随机推荐

  1. socket & pipe note

    [socket & pipe note] 1.socket类型 2.大小端 3.socketpair 如何创建全双工管道? 直接的办法当然是pipe两次,创建两组管道,但是有没有更简单的呢? ...

  2. 多产生半成品工单的问题 修改带SO的半成品工单无法分配给SO的问题的

    原因:验货及VIP带SO的半成品MO无法分配给对应的SO问题, 解决: SELECT SL.ENTERPRISE , SL.ENGINE_ID , SL.SITEID , ML.MO_ID || '_ ...

  3. testng参数化(提供测试数据)

    testng提供测试数据的两个注释:@DataProvide和@Parameter   一.通过testng.xml中设置参数 (实际上testng.xml只是一个名字,可以起任何一个名字,只要是.x ...

  4. linux shell脚本编程笔记(五): 重定向

    I/O重定向 简述: 默认情况下始终有3个"文件"处于打开状态, stdin (键盘), stdout (屏幕), and stderr (错误消息输出到屏幕上). 这3个文件和其 ...

  5. Python3 sorted() 函数

    Python3 sorted() 函数  Python3 内置函数 描述 sorted() 函数对所有可迭代的对象进行排序操作. sort 与 sorted 区别: sort 是应用在 list 上的 ...

  6. JQuery常用函数及功能

    JQuery常用函数及功能小结 来源:http://blog.csdn.net/screensky/article/details/7831000 1.文档加载完成执行函数 $(document).r ...

  7. 向值栈放List集合

    ------------------siwuxie095 向值栈放 List 集合 1.具体步骤 (1)在 Action 中定义 List 集合对象 (2)提供 List 集合对象的 get 方法 ( ...

  8. 输入输出参数 inout

    输入输出参数 inout 函数参数默认是常量.试图在函数体中更改参数值将会导致编译错误(compile-time error).这意味着你不能错误地更改参数值.如果你想要一个函数可以修改参数的值,并且 ...

  9. Associate File Type with Qt In Mac Os and Win

    Win Registry Question One day, my boss want me to finish one function which let the users can double ...

  10. re 正则模块

    re模块(* * * * *) 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译成一系列 ...