傳送門node
太菜了連\(D\)都作不出來沒有小裙子\(QAQ\)c++
暴力把全部的數對都算出來,而後\(sort\)一下就好了數組
const int N=505; int a[N],st[N*N],top,n,k;ll res; int main(){ scanf("%d%d",&n,&k); fp(i,1,n)scanf("%d",&a[i]); fp(i,1,n)fp(j,i+1,n)st[++top]=a[i]+a[j]; sort(st+1,st+1+top); fd(i,top,top-k+1)res+=st[i]; printf("%lld\n",res); return 0; }
咱們從左到右一列一列考慮,若是該列上下都沒有,放一個黑的就夠了(具體放在上下無所謂,反正都是一個),若是這一列有,那麼和上一個有黑的列進行比較,若是它們上同有或下同有就不用管了,不然必須多放一個。具體能夠畫個圖ui
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #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;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int N=1e5+5; int mp[5][N];int n,res; inline int calc(R int i){return mp[1][i]|(mp[2][i]<<1);} int main(){ scanf("%d",&n); fp(i,1,n)scanf("%d",&mp[1][i]); fp(i,1,n)scanf("%d",&mp[2][i]); int bg=n,ed=1; fp(i,1,n)if(mp[1][i]||mp[2][i]){bg=i;break;} fd(i,n,1)if(mp[1][i]||mp[2][i]){ed=i;break;} if(bg==ed)return puts("0"),0; int las=calc(bg); fp(i,bg+1,ed)if(!mp[1][i]&&!mp[2][i])++res; else{ if((calc(i)&las)==0)++res,mp[1][i]=mp[2][i]=1; las=calc(i); } printf("%d\n",res); return 0; }
設子序列中元素個數爲\(s\),那麼這個子序列中每一個元素會被計算\(2^{s-1}\)次,那麼就是要求\(m|sum\times 2^{s-1}\)(\(sum\)表示子序列元素和)this
若是沒有\(2^{s-1}\),那麼能夠直接跑個暴力揹包計算方案數。若是有\(2^{s-1}\),咱們發現有貢獻的\(s\)最多隻有\(O(\log m)\)個,那麼咱們開\(O(\log m)\)個揹包就行了,每加一個數就令\(m/=2\)spa
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #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;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int N=5005,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 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 f[21][N],g[21][N],st[21],a[N],top,n,m,res; int main(){ scanf("%d%d",&n,&m); fp(i,1,n)scanf("%d",&a[i]); st[++top]=m;for(R int k=m;k&1^1;st[++top]=k>>1,k>>=1); fp(i,1,n){ fp(k,1,top)fp(s,0,st[k]-1)g[k][s]=f[k][s]; upd(g[1][a[i]%m],1); fp(k,1,top-1)fp(s,0,st[k]-1)upd(g[k+1][(s+a[i])%st[k+1]],f[k][s]); fp(s,0,st[top]-1)upd(g[top][(s+a[i])%st[top]],f[top][s]); fp(k,1,top)fp(s,0,st[k]-1)f[k][s]=g[k][s]; } fp(k,1,top)upd(res,f[k][0]); printf("%d\n",res); return 0; }
我錯了我之後不再看到\(lxl\)就想到分塊了……code
首先若是它是個單點修改能夠直接線段樹維護線性基,然而它是個區間修改我就不會作了……比賽結束以後看了看\(rqy\)的代碼發現把原數組給差分一下,區間修改就能夠變成兩個單點修改了。根據線性代數芝士原來的線性基和差分以後的線性基是等價的。注意一下邊界條件就好了get
關於爲啥邊界條件這樣處理是對的能夠感性理解一下……it
//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;} template<class T>inline bool cmin(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 K=-1,Z=0; inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} void print(R int x){ if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++K]=z[Z],--Z);sr[++K]='\n'; } const int N=50005,L=31; struct node;typedef node* ptr; struct node{ ptr lc,rc;int v[L]; inline void init(R int x){ int k=0; fp(i,0,L-1){ v[i]=0; if(x>>i&1)k=i; } v[k]=x; } void merge(ptr s,ptr t){ if(s!=this)memcpy(v,s->v,124); int k=0; fp(i,0,L-1)if(k=t->v[i]){ fd(j,i,0)if(k>>j&1){ if(!v[j]){v[j]=k;break;} k^=v[j]; } } } inline int calc(R int x){ fd(i,L-1,0)if(x>>i&1^1)x^=v[i]; return x; } inline void upd(){merge(lc,rc);} }pool[N<<2],*rt,*now,*pp=pool; int A[N],c[N],n,m,l,r,op,x; inline void upd(R int x,R int y){for(;x<=n;x+=x&-x)c[x]^=y;} inline int ask(R int x){R int res=0;for(;x;x-=x&-x)res^=c[x];return res;} void build(ptr &p,int l,int r){ p=pp++; if(l==r)return p->init(A[l]),void(); int mid=(l+r)>>1; build(p->lc,l,mid),build(p->rc,mid+1,r); p->upd(); } void update(ptr p,int l,int r,int x){ if(l==r)return p->init(A[x]),void(); int mid=(l+r)>>1; x<=mid?update(p->lc,l,mid,x):update(p->rc,mid+1,r,x); p->upd(); } void query(ptr p,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r)return now->merge(now,p),void(); int mid=(l+r)>>1; if(ql<=mid)query(p->lc,l,mid,ql,qr); if(qr>mid)query(p->rc,mid+1,r,ql,qr); } int main(){ // freopen("testdata.in","r",stdin); n=read(),m=read(),now=pp++; fp(i,1,n)A[i]=read(); fd(i,n,1)A[i]^=A[i-1]; fp(i,1,n){ c[i]^=A[i]; if(i+(i&-i)<=n)c[i+(i&-i)]^=c[i]; } build(rt,1,n); while(m--){ op=read(),l=read(),r=read(),x=read(); if(op==1){ upd(l,x),upd(++r,x); A[l]^=x,update(rt,1,n,l); if(r<=n)A[r]^=x,update(rt,1,n,r); }else{ now->init(ask(l)); if(l<r)query(rt,1,n,l+1,r); print(now->calc(x)); } } return Ot(),0; }
剩下兩題先咕了……class