• [20180811]校内模拟赛


    T1 二元组(pair)

    题目描述

    求有多少个非负整数二元组(x,y)满足xy+x+y=n。

    输入格式

    输入文件pair.in

    多组数据,第一行一个整数T表示数据组数。

    接下来T行,每行一个非负整数n,表示一个询问。

    输出格式

    输出文件pair.out

    输出T行,每行一个整数,表示答案。

    样例

    样例输入

    3
    1
    3
    4
    

    样例输出

    2
    3
    2
    

    数据范围与提示

    对于30%的数据,n≤20000,T≤1000;

    对于100%的数据,n≤10^8,T≤10000。

    Solution

    把原式转化成((x+1)(y+1)=n+1),所以只要枚举(n+1)的因数就可以了。

    #include<cstdio>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    int T,n,ans,flag;
    int main(){
    	freopen("pair.in","r",stdin);
    	freopen("pair.out","w",stdout);
    	T=read();
    	register int i;
    	while(T--){
    		n=read()+1;ans=0;flag=0;
    		for(i=1;i*i<n;i++){
    			if(n%i==0) ans++;
    		}
    		if(i*i==n) flag=1;
    		printf("%d
    ",(ans<<1)+flag);
    	}
    	return 0;
    }
    

    T2 排列计数(permutation)

    题目描述

    求有多少个1到n的排列满足恰有k对在排列中相邻的数满足前小于后,答案对2012取模。

    输入格式

    输入文件permutation.in

    一行2个正整数n,k。

    输出格式

    输出文件permutation.out

    输出一个整数表示答案。

    样例

    样例输入

    5 2
    

    样例输出

    66
    

    数据范围与提示

    对于30%的数据,n≤10。

    对于100%的数据,k<n≤1000。

    Solution###

    当初的做法时一个(O(kn^3))的加上一个前缀和优化,卡过了70分。

    正解:用f[i][j]表示当n=i,k=j时的方案数,考虑往i的排列中插入一个i+1,插在什么位置会让j加1,容易得到

    [f[i][j]=(i+1)*f[i-1][j]+(i-j)*f[i-1][j-1] ]

    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    #define MN 1005
    #define mod 2012
    int n,K,ans;
    //int f[2][MN][MN][3];
    int f[MN][MN]; 
    inline void add(int &x,int y){x+=y;x%=mod;}
    int main(){
    	freopen("permutation.in","r",stdin);
    	freopen("permutation.out","w",stdout);
    	n=read(),K=read();
    /*暴力dp-70分 
    	register int i,j,k,kk,now=0;
    	f[0][1][0][0]=1;
    	for(i=2;i<=n;i++){
    		now=1-now;
    		memset(f[now],0,sizeof f[now]);
    		f[now][0][1][0]=f[now][i-1][i][0]=1;
    		for(j=1;j<i-1;j++)for(k=i-1;k>=1;k--)
    			add(f[now][j][k][1],f[1-now][j][k][0]+f[now][j][k+1][1]);
    		for(j=1;j<i-1;j++)for(k=2;k<=i;k++)
    			add(f[now][j][k][2],f[1-now][j-1][k-1][0]+f[now][j][k-1][2]);
    		for(j=1;j<i-1;j++)for(k=1;k<=i;k++)
    			add(f[now][j][k][0],f[now][j][k][1]+f[now][j][k][2]);
    	}
    	for(i=1;i<=n;i++) add(ans,f[now][K][i][0]);
    	printf("%d
    ",ans);
    */
    	register int i,j;
    	f[1][0]=f[2][0]=f[2][1]=1;
    	for(i=3;i<=n;i++){
    		f[i][0]=f[i][i-1]=1;
    		for(j=1;j<i-1;j++) f[i][j]=((j+1)*f[i-1][j]%mod+f[i-1][j-1]*(i-j)%mod)%mod;
    	}
    	printf("%d
    ",f[n][K]);
    	return 0;
    }
    

    T3 最短路(shortest)

    题目描述

    给出一个n个点m条边的无向图,点编号为1到n。定义最短路树为一个边集满足恰好构成一棵n个点的树且1号点在树上到每个点的最短路等于其在原图中的最短路。

    给出最短路树,对除了1号点外的每个点i求从1号点出发且不经过最短路树上1到i最短路径上最后一条边的最短路长度。

    输入格式

    输入文件shortest.in

    第一行两个正整数n,m。

    接下来m行,每行四个非负整数a,b,l,t,表示有一条连接a和b且长度为l的边,若t=1,这条边为最短路树上的边;若t=0则不是最短路树上的边。

    输出格式

    输出文件shortest.out

    输出一行n−1个数,第i个表示1到i+1要求的答案,如果无解则输出-1

    样例

    样例输入

    5 9
    3 1 3 1
    1 4 2 1
    2 1 6 0
    2 3 4 0
    5 2 3 0
    3 2 2 1
    5 3 1 1
    3 5 2 0
    4 5 4 0
    

    样例输出

    6 7 8 5
    

    数据范围与提示

    对于30%的数据,n≤100,m≤2000。

    对于100%的数据,n≤4000,m,l≤10^5。

    Solution####

    原题时BZOJ的3694。

    到点i的最优路径必然是先沿树边走到子树i以外的一个点,再走一条非树边进子树i,然后沿树边走到i。枚举一条a走到b长度为L的边,a在子树外b在子树内,对点i的贡献是d[a]+L+d[b]-d[i],由于-d[i]只跟i有关,只要对一个i求满足条件的最小的d[a]+L+d[b]

    怎么求呢。根据最优路径的走法,对于一对a和b,其实只会影响到a、b到lca(a,b)(不包括lca)的两条链,把所有的d[a]+L+d[b]按照大小排序后,一旦一个节点被更新后,就不会再被更新。用并查集维护,将被跟新后的链上元素全部指向链顶,这样就可以轻松地从a,b往lca上跳,且不会更新哪些已经被赋值地节点了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    #define MN 4005
    #define ME 100005 
    struct edge{int to,w,nex;}e[MN<<1];int cnt=0,hr[MN];
    inline void ins(int f,int t,int w){
    	e[++cnt]=(edge){t,w,hr[f]};hr[f]=cnt;
    	e[++cnt]=(edge){f,w,hr[t]};hr[t]=cnt;
    } 
    int n,m,dis[MN],Fa[MN],f[MN],bel[MN],dep[MN],pin;
    struct relation{int a,b,w;}re[ME];
    bool cmp(relation M,relation N){return M.w<N.w;}
    void dfs(int fa,int x){
    	for(int i=hr[x];i;i=e[i].nex)if(e[i].to^fa){
    		Fa[e[i].to]=x;dis[e[i].to]=dis[x]+e[i].w;dep[e[i].to]=dep[x]+1;dfs(x,e[i].to);
    	}
    }
    int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);} 
    int main(){
    	freopen("shortest.in","r",stdin);
    	freopen("shortest.out","w",stdout);
    	n=read(),m=read();
    	register int i,j,x,y,l,t;
    	for(i=1;i<=m;i++){
    		x=read(),y=read(),l=read(),t=read();
    		if(t) ins(x,y,l);
    		else re[++pin]=(relation){x,y,l};
    	}
    	dis[1]=0;dep[1]=1;dfs(0,1);
    	for(i=1;i<=n;i++) f[i]=i;
    	for(i=1;i<=pin;i++) re[i].w+=dis[re[i].a]+dis[re[i].b];
    	sort(re+1,re+pin+1,cmp);
    	for(i=1;i<=pin;i++){
    		int x=getf(re[i].a),y=getf(re[i].b);
    		while(x^y){
    			if(dep[x]<dep[y]) swap(x,y);
    			bel[x]=i;
    			x=f[x]=getf(Fa[x]);
    		}
    	}
    	for(i=2;i<=n;i++){
    		if(bel[i]) printf("%d ",re[bel[i]].w-dis[i]);
    		else printf("-1 ");
    	}
    	return 0;
    }
    

    Blog来自PaperCloud,未经允许,请勿转载,TKS。

  • 相关阅读:
    MongoDB ‘conn’Mongo 对象远程代码执行漏洞
    Linux Kernel 本地拒绝服务漏洞
    Linux Kernel ‘skbuff.c’本地拒绝服务漏洞
    WordPress Citizen Space插件跨站请求伪造漏洞
    OpenSSH远程拒绝服务漏洞
    Bug之王花落谁家:四大最危险编程语言,PHP竟然不是bug最多的语言!
    《出Bug表》假如诸葛亮是程序员!写Bug测Bug,不宜异同!
    关于程序员的段子,有没有get到你的点?单身的程序员才是完整的程序员!
    关于程序员的段子,有没有get到你的点?单身的程序员才是完整的程序员!
    socket 通信 入门3 android 客户端 C# 服务端
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/9461818.html
Copyright © 2020-2023  润新知