zoukankan      html  css  js  c++  java
  • 20191008,10,12

    2019.10.08

    T1 20pts

    考试时(n^2)写挂,最后也不知道(x)用来干啥。
    70pts: (mathcal{O}(n^2))
    (f_i) 表示一行和为 (i) 的方案数。显然
    (f_i={m choose i}x^{m-i}y^i)
    (g_i) 表示一行和大于等于 (i) 的方案数。
    考虑枚举最大值是多少,多少个 (B) 是等于这个最大值,那么答案显然为
    (sum_{i=0}^msum_{j=1}^n{nchoose j}f_i^jg_{i+1}^{n-j}i)
    100pts:
    想一想,发现最小值为 (i) 的方案数为:(g_i^n-g_{i+1}^n)

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=200010,M=1000000007;
    int n,m,x,y,fac[N],Inv[N],rfac[N],sum[N],a[100],ans;
    inline int C(int n,int m) {
    	return 1ll*fac[n]*rfac[m]%M*rfac[n-m]%M;
    }
    inline int qpow(int a,int b) { R ret=1;
    	for(;b;b>>=1,a=1ll*a*a%M) if(b&1) ret=1ll*ret*a%M; return ret;
    }
    inline void main() {
    //	freopen("past.in","r",stdin);
    //	freopen("past.out","w",stdout);
    //	n=g(),m=g(),x=g(),y=g();
    //	fac[0]=fac[1]=1; for(R i=2;i<=max(n,m);++i) fac[i]=1ll*fac[i-1]*i%M;
    //	Inv[0]=Inv[1]=1; for(R i=2;i<=max(n,m);++i) Inv[i]=M-1ll*M/i*Inv[M%i]%M;
    //	rfac[0]=rfac[1]=1; for(R i=2;i<=max(n,m);++i) rfac[i]=1ll*rfac[i-1]*Inv[i]%M;
    //	for(R k=m;k>=0;--k) { 
    //		R tmp=1ll*C(m,k)*qpow(x,m-k)%M*qpow(y,k)%M,inv=qpow(sum[k+1],M-2); 
    //		R t=tmp,I=qpow(sum[k+1],n-1); R ttt=1ll*C(m,k)*qpow(x,m-k)%M*qpow(y,k)%M;
    //		for(R i=1;i<=n;++i) {
    //			if(n==i) I=1;
    //			ans=(ans+1ll*C(n,i)*tmp%M*I%M*k)%M; 
    //			tmp=1ll*tmp*t%M,I=1ll*I*inv%M; 
    //		} sum[k]=(sum[k+1]+1ll*C(m,k)*qpow(x,m-k)%M*qpow(y,k))%M;
    //	} printf("%d
    ",ans);
    	n=g(),m=g(),x=g(),y=g();
    	fac[0]=fac[1]=1; for(R i=2;i<=max(n,m);++i) fac[i]=1ll*fac[i-1]*i%M;
    	Inv[0]=Inv[1]=1; for(R i=2;i<=max(n,m);++i) Inv[i]=M-1ll*M/i*Inv[M%i]%M;
    	rfac[0]=rfac[1]=1; for(R i=2;i<=max(n,m);++i) rfac[i]=1ll*rfac[i-1]*Inv[i]%M;	
    	for(R i=m;~i;--i) sum[i]=(sum[i+1]+1ll*C(m,i)*qpow(x,m-i)%M*qpow(y,i))%M;
    	for(R i=1;i<=m;++i) ans=(ans+1ll*(qpow(sum[i],n)-qpow(sum[i+1],n)+M)*i%M)%M;
    	printf("%d
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    T2 60pts

    操作树。。。考试时失了智写的压位。。。于是改题时接着压位。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define ll long long
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    }	const int M=100010; const short B=32; const unsigned E=-1,S=31,T=5;
    unsigned mem[31255]; int n,m,k,ans[M],sum;
    #define P(i,j) ((i-1)*m+j-1)
    struct node {int op,h,l;}q[M];
    vector <int> e[M];
    const unsigned char __popcount_tab[] = {
      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
      3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
    };
     
    inline int __builtin_popcount (unsigned x) {
      return __popcount_tab[(x >> 0) & 0xff]  + __popcount_tab[(x >>  8) & 0xff]  + __popcount_tab[(x >> 16) & 0xff] + __popcount_tab[(x >> 24) & 0xff];
    }
    inline void operation(int whi) {
    	register short p1,p2,q1,q2;
    	register unsigned ll tmp;
    	register int pos1,pos2,pos;
    	register int op=q[whi].op,h=q[whi].h,l=q[whi].l;
    	if(op==1) {pos=P(h,l); p1=pos>>T,p2=pos&S; ((mem[p1]>>(p2))&1)?--sum:++sum; mem[p1]^=(1u<<p2);} 
    	else if(op==2) {
    		pos1=P(h,1),pos2=P(h,m),p1=pos1>>T,q1=pos2>>T;
    		if(p1==q1) { p2=pos1&S,q2=pos2&S; 
    			tmp=((((mem[p1]>>p2)<<p2)<<(B-q2-1)));
    			sum+=(pos2-pos1+1-2*__builtin_popcount(tmp));
    			tmp=(((E>>p2)<<p2)<<(B-q2-1))>>(B-q2-1); mem[p1]^=tmp;
    		} else if(p1+1==q1) { 
    			p2=pos1&S,q2=pos2&S;tmp=mem[p1]>>p2; 
    			sum+=(B-p2-2*__builtin_popcount(tmp));
    			tmp=(E>>p2)<<p2;mem[p1]^=tmp,q2=B-q2-1;tmp=mem[q1]<<q2;
    			sum+=(B-q2-2*__builtin_popcount(tmp));
    			tmp=(E<<q2)>>q2;mem[q1]^=tmp;
    		} else {
    			p2=pos1&S,q2=pos2&S;tmp=mem[p1]>>p2;
    			sum+=(B-p2-2*__builtin_popcount(tmp));
    			tmp=(E>>p2)<<p2;mem[p1]^=tmp;q2=B-q2-1;tmp=mem[q1]<<q2;
    			sum+=(B-q2-2*__builtin_popcount(tmp));
    			tmp=(E<<q2)>>q2;mem[q1]^=tmp;
    			for(R j=p1+1,lim=q1-1;j<=lim;++j) 
    				sum+=(B-2*__builtin_popcount(mem[j])),mem[j]^=E;
    		} 
    	} else if(op==3) {
    		pos=P(0,l); for(R j=1;j<=n;++j) { pos+=m; p1=pos>>T,p2=pos&S;
    			((mem[p1]>>p2)&1)?--sum:++sum; mem[p1]^=1u<<p2;
    		}
    	}
    }
    inline void dfs(int u) { operation(u); ans[u]=sum; 
    	for(R i=0,lim=e[u].size();i<lim;++i) dfs(e[u][i]); operation(u); 
    }
    inline void main() {
    	n=g(),m=g(),k=g(); 
    	for(R i=1,op;i<=k;++i) { op=q[i].op=g();
    		if(op==1) q[i].h=g(),q[i].l=g(); if(op==2) q[i].h=g();
    		if(op==3) q[i].l=g(); if(op==4) q[i].h=g(),e[q[i].h].push_back(i);
    		else e[i-1].push_back(i);
    	} dfs(0); for(R i=1;i<=k;++i) printf("%d
    ",ans[i]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    T3 0pts

    由于关键节点很少,考虑状压。
    我们发现,如果按顺序从小到大填入数字,必须先填关键点,再填关键点旁边的点。
    我们要先预处理与关键点有关的点的点集(同时包括关键点)。
    (f[i][S])表示这个点集中填了(i)个点,关键点的状态是(S)
    转移:填一个关键点,或填一个与关键点有关的点。

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=10010,M=1000000007;
    const int dx[]={-1,0,1,-1,0,1,-1,0,1},dy[]={1,1,1,0,0,0,-1,-1,-1};
    struct node { int x,y; node() {}
    	node(int _x,int _y) {x=_x,y=_y;}
    }; vector <node> s; bool flg[150][150],vis[150];
    int n,m,k,h[N],lim,fac[N],rfac[N],x[N],y[N],f[150][N];
    inline int qpow(int a,int b) { R ret=1;
    	for(;b;b>>=1,a=1ll*a*a%M) if(b&1) ret=1ll*ret*a%M; return ret; 
    }
    inline void main() {
    	n=g(),m=g(),k=g(); lim=1<<k;
    	//freopen("out.out","w",stdout);
    	fac[0]=fac[1]=1; for(R i=2;i<=n*m;++i) fac[i]=1ll*fac[i-1]*i%M;
    	rfac[n*m]=qpow(fac[n*m],M-2); rfac[0]=rfac[1]=1;
    	for(R i=n*m;i>=3;--i) rfac[i-1]=1ll*rfac[i]*i%M;
    	for(R i=0;i<k;++i) x[i]=g(),y[i]=g();
    	for(R i=0;i<k;++i) for(R j=0;j<9;++j) {
    		R X=x[i]+dx[j],Y=y[i]+dy[j];
    		if(X<1||X>n||Y<1||Y>m||flg[X][Y]) continue;
    		flg[X][Y]=true,s.push_back(node(X,Y));
    	} 
    	for(R i=0;i<lim;++i) { 
    		memset(vis,0,sizeof vis);
    		for(R j=0;j<k;++j) if(!(i>>j&1)) {
    			for(R l=0;l<s.size();++l)
    				if(!(s[l].x==x[j]&&s[l].y==y[j])&&abs(s[l].x-x[j])<=1&&abs(s[l].y-y[j])<=1) 
    					vis[l]=1; 
    		} for(R j=0;j<s.size();++j) if(vis[j]) ++h[i];
    	} f[0][0]=1;
    	for(R i=0;i<s.size();++i) {
    		for(R j=0;j<lim;++j) { R num=0;
    			for(R l=0;l<k;++l) if(!(j>>l&1)) 
    				(f[i+1][j^(1<<l)]+=f[i][j])%=M,++num;
    			if(s.size()-i-h[j]-num>0) f[i+1][j]=(f[i+1][j]+1ll*(s.size()-i-h[j]-num)*f[i][j])%M;//判断能否填与关键点有关的点
    		}
    	} printf("%d
    ",1ll*f[s.size()][lim-1]*fac[n*m]%M*rfac[s.size()]%M);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.10.10

    T1 100pts

    没话。
    %最小生成树的那个神仙

    #include<bits/stdc++.h>
    #define R register int 
    #define ll long long
    using namespace std;
    namespace Luitaryi { 
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=1010,M=1000010;
    int n,m,tx,ty,cnt; char s[N];
    int vr[M<<2],nxt[M<<2],fir[M],w[M<<2],d[M];
    bool vis[M],a[N][N];
    inline void add(int u,int v,int ww) {
    	vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww;
    	vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt,w[cnt]=ww;
    }
    #define P(i,j) ((i-1)*m+j)
    priority_queue<pair<int,int> > q;
    inline void dijk() {
    	memset(d,0x3f,sizeof d); d[P(n,1)]=0;
    	q.push(make_pair(0,P(n,1)));
    	while(q.size()) { R u=q.top().second; q.pop(); 
    		if(vis[u]) continue; vis[u]=1;
    		for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    			if(d[v]>max(d[u],w[i])) {
    				d[v]=max(d[u],w[i]); 
    				q.push(make_pair(-d[v],v));
    			}
    		}
    	}
    }
    inline void main() {
    	n=g(),m=g(); for(R i=1;i<=n;++i) {
    		scanf("%s",s+1); for(R j=1;j<=m;++j) a[i][j]=(s[j]=='#');
    	} tx=g(),ty=g(); 
    	for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) if(a[i][j]) { R p=1;
    		while(i-p>0&&!a[i-p][j]) ++p;
    		if(i-p>0) add(P(i,j),P(i-p,j),p);
    		if(a[i][j-1]) add(P(i,j),P(i,j-1),0);
    		//if(a[i][j+1]) add(P(i,j),P(i,j+1),0);
    	} dijk(); printf("%d
    ",d[P(tx,ty)]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    T2

    我们假设刚开始所有数都在集合 (A),而集合 (B) 是空的。
    所以我们有 (R_A-L_B>R_B-L_A) (显然吧)
    然后我们可以把 (A) 中的一些东西转到 (B) 中,设所有转移的两个端点和分别为(l,r)
    (R_A-r-(L_B+l)>(R_B+r)-(L_A-l))
    (R_A-R_B+L_A-L_B>2*(l+r))
    于是背包。
    奉上最短的代码:

    #include<bits/stdc++.h>
    using namespace std;int l,r,R,s;bitset<40001>f=1;main(){for(cin>>l;cin>>l>>r;)R+=r,s+=l+=r,f|=f<<l;for(s/=2;!f[s];--s);cout<<R-s;}
    

    T3 0pts

    考场上把 change 和 query 写到一起,成功保龄
    我们发现模数很奇怪,于是打打表,发现平方一会就不变了。。。于是和区间开根基本一样了。

    #include<bits/stdc++.h>
    #define R register int 
    #define ll unsigned long long
    using namespace std;
    namespace Luitaryi { 
    inline ll g() { register ll x=0;
    	register char ch; while(!isdigit(ch=getchar()));
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x;
    } 
    inline int gi() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x;
    } const int N=65540; const ll M=2305843008676823040ull;
    int n,m; ll sum[N<<2]; bool flg[N<<2];
    #define ls (tr<<1)
    #define rs (tr<<1|1)
    inline void mod(ll& a,ll b) {a+=b; if(a>=M) a-=M;}
    inline ll mode(ll a,ll b) {a+=b; if(a>=M) a-=M; return a;}
    inline ll mul(ll a,ll b) {
    	register unsigned __int128 t=a;
    	t=t*b%M; return t;
    }
    inline void build(int tr,int l,int r) {
    	if(l==r) {sum[tr]=g(); return ;} R md=l+r>>1;	
    	build(ls,l,md),build(rs,md+1,r); sum[tr]=(sum[ls]+sum[rs])%M;
    }
    inline void change(int tr,int l,int r,int LL,int RR) {
    	if(l==r) { register ll tmp=sum[tr]; 
    		sum[tr]=mul(sum[tr],sum[tr]); 
    		flg[tr]=(sum[tr]==tmp); return ;
    	} R md=l+r>>1;
    	if(LL<=md&&!flg[ls]) change(ls,l,md,LL,RR);
    	if(RR>md&&!flg[rs]) change(rs,md+1,r,LL,RR);
    	sum[tr]=mode(sum[ls],sum[rs]); flg[tr]=flg[ls]&&flg[rs];
    }
    inline ll query(int tr,int l,int r,int LL,int RR) {
    	if(LL<=l&&r<=RR) return sum[tr]; R md=l+r>>1; register ll ret=0;
    	if(LL<=md) ret=query(ls,l,md,LL,RR);
    	if(RR>md) mod(ret,query(rs,md+1,r,LL,RR)); return ret;
    }
    inline void main() {
    	n=gi(),m=gi(); build(1,1,n);
    	for(R i=1,l,r;i<=m;++i) 
    		l=gi(),r=gi(),printf("%llu
    ",query(1,1,n,l,r)),change(1,1,n,l,r);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.10.12

    T1 90pts

    大模拟。。。有一个点写错了,竟然还有分(万幸)

    #include<bits/stdc++.h>
    #define R register int
    #define ll long long
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    }
    inline int g(char* s) { R x=0,f=1;
    	register char ch; while(!isdigit(ch=*s++)) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=*s++)); return x*f;
    } const int N=10;
    char s[5]; int a[N],b[N],anss[N],c[N<<1],ans=8,tp;
    inline void main() {
    	for(R i=1;i<=7;++i) {
    		scanf("%s",s); if(isalpha(s[0])) {
    			if(s[0]=='A') a[i]=14; if(s[0]=='J') a[i]=11;
    			if(s[0]=='Q') a[i]=12; if(s[0]=='K') a[i]=13;
    		} else a[i]=g(s);
    	} swap(a[1],a[6]),swap(a[2],a[7]);
    	for(R i=1;i<=7;++i) for(R j=i+1;j<=7;++j) 
    	for(R k=j+1;k<=7;++k) for(R l=k+1;l<=7;++l) 
    	for(R m=l+1;m<=7;++m) {
    		memset(c,0,sizeof c),tp=7;
    		b[1]=a[l],b[2]=a[m],b[3]=a[i],b[4]=a[j],b[5]=a[k];
    		sort(b+1,b+6,greater<int>()); for(R t=1;t<=5;++t) {
    			++c[b[t]]; if(c[b[t]]==4) tp=1;
    			else if(c[b[t]]==3) {
    				if(tp==5) tp=2; else tp=4;
    			} else if(c[b[t]]==2) {
    				if(tp==6) tp=5; else if(tp==4) tp=2; else tp=6;
    			}
    		} register bool fg=true;
    		if(tp==7) {for(R t=2;t<=5;++t) fg&=(b[t-1]-b[t]==1); if(fg) tp=3;
    			else if(b[1]==14) { R p=1; fg=true;
    				while(b[p]==14) b[p]=1,++p;
    				sort(b+1,b+6,greater<int>());
    				for(R t=2;t<=5;++t) fg&=(b[t-1]-b[t]==1);
    				if(fg) tp=3;
    				p=5; while(b[p]==1) b[p]=14,--p;
    				if(!fg) sort(b+1,b+6,greater<int>());
    			}	
    		}			
    		if(tp<ans) ans=tp,memcpy(anss,b,sizeof anss);
    		else if(tp==ans) {
    			for(R t=1;t<=5;++t) {
    				if(b[t]>anss[t]) {
    					memcpy(anss,b,sizeof anss); break;
    				} if(b[t]<anss[t]) break;
    			}
    		}
    	}
    	for(R i=1;i<=5;++i) {
    		if(anss[i]>10) {
    			if(anss[i]==11) putchar('J'); if(anss[i]==12) putchar('Q');
    			if(anss[i]==13) putchar('K'); if(anss[i]==14) putchar('A');
    			putchar(' ');
    		} else printf("%d ",anss[i]);
    	}
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    T2 50pts

    竟然写的二分差值。。。但是0怎么办?(又是万幸没卡死我)
    于是我们发现,当我们取的数越接近这段的平均数,越优。
    又因为序列是不减的,所以平均数也是不减的,所以平均数的位置也是不减的。
    %那个写斜率优化的神仙

    #include<bits/stdc++.h>
    #define R register int
    #define ll long long
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=100010;
    int n,k,a[N],t=1;
    ll p[N],ps[N],ans=4e18;
    inline void main() {
    	n=g(),k=g(); for(R i=1;i<=n;++i) a[i]=g();
    	for(R i=1;i<=n;++i) p[i]=p[i-1]+a[i];
    	for(R i=1;i<=n;++i) ps[i]=ps[i-1]+1ll*a[i]*a[i];
    	for(R i=k,LL,RR;i<=n;++i) { LL=i-k,RR=i;
    		while(1ll*k*a[t]*a[t]-2*a[t]*(p[RR]-p[LL])+ps[RR]-ps[LL]>=
    					1ll*k*a[t+1]*a[t+1]-2*a[t+1]*(p[RR]-p[LL])+ps[RR]-ps[LL]&&t<RR) ++t;
    		ans=min(ans,1ll*k*a[t]*a[t]-2*a[t]*(p[RR]-p[LL])+ps[RR]-ps[LL]);
    	} printf("%lld
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    T3

    咕?

  • 相关阅读:
    C# 从服务器下载文件
    不能使用联机NuGet 程序包
    NPOI之Excel——合并单元格、设置样式、输入公式
    jquery hover事件中 fadeIn和fadeOut 效果不能及时停止
    UVA 10519 !! Really Strange !!
    UVA 10359 Tiling
    UVA 10940 Throwing cards away II
    UVA 10079 Pizze Cutting
    UVA 763 Fibinary Numbers
    UVA 10229 Modular Fibonacci
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11675328.html
Copyright © 2011-2022 走看看