zoukankan      html  css  js  c++  java
  • 【noip2012】

    noip2012

    Vigenère 密码

    模拟

    用的以前的方法 然后我康了康yyb的 发现我好菜

    int r[30][30];
    void pre(){
    	for(int i=1;i<=26;++i)
    		for(int j=0;j<=26-i;++j)
    			r[i][i+j]=j+1;
    	for(int i=2;i<=26;++i)
    		for(int j=28-i;j<=26;++j)
    			r[i][j-27+i]=j;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	pre();
    	scanf("%s%s",k,c);
    	lk=strlen(k),lc=strlen(c);
    	for(int i=0,cur=0,x,y,xx;i<lc;++i,++cur){
    		if(cur>=lk) cur=0;xx=0;
    		if(c[i]>='A'&&c[i]<='Z') x=c[i]-'A'+1;
    		else if(c[i]>='a'&&c[i]<='z') xx=1,x=c[i]-'a'+1;
    		if(k[cur]>='A'&&k[cur]<='Z') y=k[cur]-'A'+1;
    		else if(k[cur]>='a'&&k[cur]<='z') y=k[cur]-'a'+1;
    		if(xx) printf("%c",r[y][x]+96);
    		else printf("%c",r[y][x]+64);
    	}
        return 0;
    }
    
    char get(char a,char b){return (((b-97)-(a-97)+26)%26)+97;}
    int main(){
        scanf("%s",k);scanf("%s",c);
        for(int i=0,x,l=strlen(c),lk=strlen(k);i<l;++i){
            x=0;
            if(c[i]>='A'&&c[i]<='Z') c[i]+=32,x=-32;
            if(k[i%lk]>='A'&&k[i%lk]<='Z') k[i%lk]+=32;
            putchar(get(k[i%lk],c[i])+x);
        }
        puts("");return 0;
    }
    

    国王游戏

    贪心+高精

    每个大臣获得的金币数分别为:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数 使获得奖赏最多的大臣尽可能少

    对于国王身后两个点来分析 队列可能为

    (L) (R) (L) (R)

    (king)(a_0) (b_0) (king): (a_0) (b_0)

    (P_1)(a_1) (b_1) (P_2)(a_2) (b_2)

    (P_2)(a_2) (b_2) (P_1)(a_1) (b_1)

    (ans1=max(frac{a_0}{b1},frac{a_0*a_1}{b_2})) (ans_2=max(frac{a_0}{b_2},frac{a_0*a_2}{b_1}))

    显然可以得到(frac{a_0*a_1}{b_2}>frac{a_0}{b_2}),(frac{a_0*a_2}{b_1}>frac{a_0}{b_1})

    (ans_1<ans_2)(frac{a_0*a_2}{b_1}>frac{a_0*a_1}{b_2})(a_2*b_2>a_1*b_1)

    所以按(a_i*b_i)为关键字来排序就好

    重温(?)高精

    struct node{int a,b,c;}a[N];
    bool cmp(node x,node y){return x.c<y.c;}
    
    struct num{
    	int a[N];
    	num(){memset(a,0,sizeof(a));}
    	num(int x){
    		memset(a,0,sizeof(a));
    		int t=0;
    		while(x) a[++t]=x%base,x/=base;
    		a[0]=t;
    	}
    	void print(){
    		printf("%d",a[a[0]]);
    		for(int i=a[0]-1;i;--i) printf("%04d",a[i]);
    		puts("");
    	} 
    }pai,p,nw,ans;
    bool operator <(const num &p,const num &q){
    	if(p.a[0]<q.a[0]) return 1;
    	if(p.a[0]>q.a[0])  return 0;
    	for(int i=p.a[0];i;--i) if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i];
    	return 0;
    }
    num operator +(const num &p,const num &q){
    	num c;c.a[0]=Max(p.a[0],q.a[0]);
    	for(int i=1;i<=c.a[0];++i)
    		c.a[i]+=p.a[i]+q.a[i],c.a[i+1]+=c.a[i]/base,c.a[i]%=base;
    	if(c.a[c.a[0]+1]) ++c.a[0];
    	return c;
    }
    num operator -(const num &p,const num &q){
    	num c=p;
    	for(int i=1;i<=q.a[0];++i){
    		c.a[i]-=q.a[i];
    		if(c.a[i]<0) --c.a[i+1],c.a[i]+=base;
    	}
    	while(c.a[0]&&!c.a[c.a[0]]) --c.a[0];
    	return c;
    }
    num operator *(const num &p,const num &q){
    	num c;c.a[0]=p.a[0]+q.a[0]-1;
    	for(int i=1;i<=p.a[0];++i)
    		for(int j=1;j<=q.a[0];++j)
    			c.a[i+j-1]+=p.a[i]*q.a[j],c.a[i+j]+=c.a[i+j-1]/base,c.a[i+j-1]%=base;
    	while(c.a[c.a[0]+1]) ++c.a[0];
    	return c;
    }
    num operator /(const num &p,const int &q){
    	num x;x.a[0]=p.a[0];int y=0;
    	for(int i=p.a[0];i;--i){
    		y=y*base+p.a[i];
    		if(y>=q) x.a[i]=y/q,y%=q;
    	}
    	while(x.a[0]&&!x.a[x.a[0]]) --x.a[0];
    	return x;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(n);
    	for(int i=0,x,y;i<=n;++i)  rd(x),rd(y),a[i]=(node){x,y,x*y};
    	sort(a+1,a+n+1,cmp);
    	pai=num(a[0].a);
    	for(int i=1;i<=n;++i){
    		p=num(a[i].a),q=a[i].b;
    		nw=pai/q,pai=pai*p;
    		if(ans<nw) ans=nw;
    	}
    	ans.print();
        return 0;
    }
    

    开车旅行

    倍增

    详细版

    预处理出(to[i][j],da[i][j],db[i][j])表示从(i)出发小(A)和小(B)经过(2^j)轮后到达的地点、小(A)走的路程、小(B)走的路程

    预处理时询问第一近和第二近的地点用双向链表

    (code)

    struct node{int h,id;}a[N];
    bool cmp(node x,node y){return x.h<y.h;}
    
    int pos[N][2],to[N][20];
    void upd(int nw,int x){
    	ll d=abs(h[nw]-a[x].h);
    	if(dis[nw][0]>d||(dis[nw][0]==d&&a[x].h<h[pos[nw][0]])) 
    		dis[nw][1]=dis[nw][0],dis[nw][0]=d,pos[nw][1]=pos[nw][0],pos[nw][0]=a[x].id;
    	else if(dis[nw][1]>d||(dis[nw][1]==d&&a[x].h<h[pos[nw][1]]))
    		dis[nw][1]=d,pos[nw][1]=a[x].id;
    	
    }
    void erase(int x){nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x];}
    void prepa(){
    	for(int i=1,nw,l1,l2,r1,r2;i<=n;++i){
    		nw=id[i],l1=pre[nw],l2=pre[l1],r1=nxt[nw],r2=nxt[r1];
    		pos[i][0]=pos[i][1]=0,dis[i][0]=dis[i][1]=inf;
    		if(l1&&l1!=n+1) upd(i,l1);
    		if(l2&&l2!=n+1) upd(i,l2);
    		if(r1&&r1!=n+1) upd(i,r1);
    		if(r2&&r2!=n+1) upd(i,r2);
    		erase(nw);
    	}
    	for(int i=1;i<=n;++i) to[i][0]=pos[pos[i][1]][0],da[i][0]=dis[i][1],db[i][0]=dis[pos[i][1]][0];
    	for(int j=1;j<=17;++j)
    		for(int i=1;i<=n;++i)
    			to[i][j]=to[to[i][j-1]][j-1],da[i][j]=da[i][j-1]+da[to[i][j-1]][j-1],db[i][j]=db[i][j-1]+db[to[i][j-1]][j-1];
    }
    
    void query(int s,int lim,ll &A,ll &B){
    	for(int i=17;i>=0;--i)
    	if(to[s][i]&&da[s][i]+db[s][i]<=lim)
    		lim-=da[s][i]+db[s][i],A+=da[s][i],B+=db[s][i],s=to[s][i];
    	if(pos[s][1]&&dis[s][1]<=lim) A+=dis[s][1];
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(n);
    	for(int i=1;i<=n;++i) rd(h[i]),a[i]=(node){h[i],i};
    	sort(a+1,a+n+1,cmp);
    	for(int i=1;i<=n;++i) id[a[i].id]=i,pre[i]=i-1,nxt[i]=i+1;
    	rd(x0),rd(m),pre[0]=nxt[n+1]=0,pre[n+1]=n,nxt[0]=1;
    	prepa();
    	ll A,B;double mn=inf,ret;int ans;
    	for(int i=1;i<=n;++i){
    		query(i,x0,A=0,B=0);
    		if(!B) continue;
    		ret=(A*1.0)/(B*1.0);
    		if(mn>ret)  mn=ret,ans=i;
    		else if(ret==mn) if(h[i]>h[ans]) ans=i;
    	}
    	printf("%d
    ",ans);
    	for(int i=1,s,lim;i<=m;++i){
    		rd(s),rd(lim),A=0,B=0;
    		query(s,lim,A,B);
    		printf("%lld %lld
    ",A,B);
    	}
    	return 0;
    }
    

    同余方程

    换了一种写法ovo

    void exgcd(ll a,ll b,ll &x,ll &y){
    	if(b) exgcd(b,a%b,y,x),y-=x*(a/b);
    	else x=1,y=0;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(A),rd(B);
    	exgcd(A,B,x,y);
    	printf("%lld",(x%B+B)%B);
        return 0;
    }
    

    借教室

    原来的写法是线段树==

    大佬都说二分的复杂度是正确的

    二分+差分 每次二分第(mid)个人无法满足 然后利用差分数组 判断

    int tmp[N];
    bool check(int mid){
    	for(int i=1;i<=n;++i) tmp[i]=0;
    	for(int i=1;i<=mid;++i) tmp[s[i]]+=b[i],tmp[t[i]+1]-=b[i];
    	for(int i=1;i<=n;++i){
    		tmp[i]+=tmp[i-1];
    		if(tmp[i]>a[i]) return 0;
    	}
    	return 1;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(n),rd(m);
    	for(int i=1;i<=n;++i) rd(a[i]);
    	for(int i=1;i<=m;++i) rd(b[i]),rd(s[i]),rd(t[i]);
    	int l=1,r=n,mid,ans=0;
    	while(l<=r){
    		mid=l+r>>1;
    		if(check(mid)) l=mid+1;
    		else ans=mid,r=mid-1;
    	}
    	if(!ans) puts("0");
    	else printf("-1
    %d
    ",ans);
    	return 0;
    }
    

    疫情控制

    这个好有毒啊

    先倍增预处理 然后二分+贪心

    这个贪心应该好好想一想

    int tot=0,head[N];
    struct edge{int v,w,nxt;}e[N<<1];
    void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
    
    int f[N][20];ll len[N],dis[N][20];
    void dfs(int u,int ff){
    	for(int i=head[u],v;i;i=e[i].nxt)
    	if((v=e[i].v)!=ff) f[v][0]=u,dis[v][0]=e[i].w,len[v]=len[u]+e[i].w,dfs(v,u);
    }
    void doubling(){
    	for(int j=1;j<=16;++j)
    		for(int i=1;i<=n;++i)
    			f[i][j]=f[f[i][j-1]][j-1],dis[i][j]=dis[i][j-1]+dis[f[i][j-1]][j-1];
    }
    int getf(int x){
    	for(int i=16;i>=0;--i) if(f[x][i]>1) x=f[x][i];
    	return x;
    }
    int jump(int x,int ste){
    	for(int i=16;i>=0&&ste;--i)
    		if(f[x][i]&&dis[x][i]<=ste) ste-=dis[x][i],x=f[x][i];
    	return x;
    }
    
    struct node{int st,ret;}c[N];
    bool vis[N];int cnt,unf[N];
    bool cmp1(node x,node y){return x.ret<y.ret;}
    bool cmp2(int x,int y){return len[x]<len[y];}
    void dfs2(int u,int ff){
    	if(vis[u]) return;
    	bool ok=1,notle=0;
    	for(int i=head[u],v;i;i=e[i].nxt)
    	if((v=e[i].v)!=ff){
    		notle=1,dfs2(v,u);
    		if(!vis[v]) ok=0;
    	}
    	vis[u]=ok&notle;
    }
    bool check(int lim){
    	memset(vis,0,sizeof(vis));
    	cnt=unf[0]=0;
    	for(int i=1,to;i<=m;++i){
    		to=jump(a[i],lim);
    		if(to!=1) vis[to]=1;
    		else c[++cnt]=(node){fr[i],lim-len[a[i]]};
    	}
    	dfs2(1,0);
    	for(int i=head[1],v;i;i=e[i].nxt) if(!vis[v=e[i].v]) unf[++unf[0]]=v;
    	sort(c+1,c+cnt+1,cmp1),sort(unf+1,unf+unf[0]+1,cmp2);
    	int pos=1;
    	for(int i=1;i<=unf[0];++i){
    		if(vis[unf[i]]) continue;
    		if(pos==cnt+1) return 0;
    		while(1){
    			if(c[pos].ret<len[unf[i]]&&pos!=cnt){
    				vis[c[pos].st]=1;
    				if(c[pos].st==unf[i]) break;
    				++pos;
    			}
    			else{
    				if(pos==cnt) break;
    				if(c[pos].st!=unf[i]&&!vis[c[pos].st]) vis[c[pos++].st]=1;
    				else break;
    			}
    		}
    		if(pos==cnt&&c[pos].ret<len[unf[i]]&&c[pos].st!=unf[i]) return 0;
    		vis[unf[i]]=1,++pos;
    	}
    	return 1;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(n) ;
    	for(int i=1,u,v,w;i<n;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
    	dfs(1,0),doubling(),rd(m);
    	for(int i=1;i<=m;++i) rd(a[i]),fr[i]=getf(a[i]);
    	int l=0,r=1000000,mid,ans;
        while(l<=r){
            mid=l+r>>1;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
    	printf("%d",l);
    	return 0;
    }
    
  • 相关阅读:
    推荐两个在线格式化JavaScript代码的网站
    JavaScript 获取未知对象的属性
    笔记本“电源已接通,未充电”的解决办法
    一个好的网站: StudioStyles
    Vertical Text with CSS(用CSS竖向排列文本)
    TSQL 行列互换
    获得enum中的枚举值
    恶搞百度
    想买个洗衣机,吓出了一身水……
    一个获取SQL Server数据库连接字符串的简单方法
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11782859.html
Copyright © 2011-2022 走看看