2018 10 04 校内模拟 模拟+组合数学+SCC,树的直径

T1: K进制
kbased.cpp
【题意】
给定一个K(2<=K<=16)进制数a,判断a是否能被K-1整除。

【输入】
第一行是一个整数 t(1<=t<=50),表示测试点数量。
对于每组数据,第一行一个整数 K,表示进制。
第二行一个 K 进制数,表示 a。保证 a 是合法的 K 进制数,没有前导 0,且只由’0’-
‘9’、’A’-‘F’构成。

【输出】
如果a可以被K-1整除,输出”yes”,否则输出”no”。

【样例输入】
2
16
2D
10
19
【样例输出】
yes
no
【数据】
对于40%的数据,a的长度不超过 5。
对于100%的数据,a的长度不超过100000。

分析:模拟
代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
void in(int &x)
{
	int f=1;x=0;char w=getchar();
	while(w<'0'||w>'9') {if(w=='-') f=-f;w=getchar();}
	while(w>='0'&&w<='9') {x=10*x+w-'0';w=getchar();}
	x*=f;
}
int main()
{
	int t;in(t);char a[100400];long long s[100400];
	while(t--)
	{
		memset(s,0,sizeof(s));
		int k;in(k);
		scanf("%s",a);
		int len=strlen(a);
		s[len-1]=1;
		long long ans=0,shu;
		for(int i=len-1;i>=0;i--)
		{
			if(i!=len-1) s[i]=(s[i+1]*1ll*k)%(k-1);	
			shu=a[i]-'0';
			if(a[i]=='A') shu=10;if(a[i]=='B') shu=11;
			if(a[i]=='C') shu=12;if(a[i]=='D') shu=13;
			if(a[i]=='E') shu=14;if(a[i]=='F') shu=15;
			ans+=(shu*s[i])%(k-1);
		}
		if(ans%(k-1)==0) printf("yes\n");
		else printf("no\n");
	}
	return 0;
}

T2: 排队
fseq.cpp
【题意】
在成都某中学有 m 个男生与 n 个女生排队,这个学校的女生比较古怪,从某个位
置(包含这个位置)开始往前数,男生的数量超过了女生的数量,女生会感觉不安全,于
是会大叫起来,为了构建和谐校园,安排队伍时应该避免这样的情况。请你计算出不会引
发尖叫的排队方案的概率。(排队方案不同定义:当且仅当某个某个位置人不一样,如男
生A、男生B ,与男生B、男生A ,2个排列是不同方案)
【 Input】
第一行1个整数, 表示测试数据的组数。
每个数据 有两个数 N,M(N个女生,M个男生)
【 Output】
对于每组数据,输出一个实数(保留到小数点后 6 位)
【 Sample Input】
3
1 0
0 1
1 1
【 Sample Output】
1.000000
0.000000
0.500000
【 Hint】
第一组:只有一个女生,一种方案且可行
第二组:只有1个男生,一种方案且不行
第三组:两种方案 女、男可行,男、女不可行,可行概率 0.5
【数据规模】
30%的数据: (测试组数<=10),(0<=N,M<=1000).
100%的数据: (测试组数=9008 ), ( 0<=N,M<=20000 ).

分析:组合数学
原题地址:https://www.lydsy.com/JudgeOnline/problem.php?id=1856
我们把排列映射到二维平面上
是男生就向上走一步
是女生就向右走一步
当路径始终在直线y=x下方时这个情况就合法
用组合数学推算出方案数即为C(M+N,M)-(M+N,M-1)
答案就是1-M/(N+1)
代码略

T3: 航班
prize.cpp
【描述】
L因为业务繁忙,经常会到处出差。因为他是航空公司的优质客户,于是某个航空
公司给了他一个优惠券。
他可以利用这个优惠券在任何一个国家内的任意城市间免费旅行,当他的路线跨国
才会产生费用。L有一个航空公司的价格表与航线。而且每个城市出发都能到所有的城
市,2个城市间可能有不止一个航班,一个国家内的 2个城市间一定有不同的路线,但是
不同国家的城市间只有一条路线。L想知道从每个城市出发到产生费用最多的城市,不过
你不能重复在一个航班上飞来飞去产生费用,不行沿最少的费用路线飞行。

【 输入】
第一行,两个整数 N,M,表示N 个城市, M 条航线。
接下来 M 行,每行三个整数 a,b,c,表示城市 a,b 之间有一条费用为 c 的航
线。
【 输出】
共 N 行,第 i 行为从城市 i 出发到达每个城市额外费用的最大值。
【 Sample Input】
6 6
1 4 2
1 2 6 2 5 3
2 3 7
6 3 4
3 1 8
【 Sample Output】
4
4
4
6
7
7
【解释】
有四个国家,包含的城市分别为 {1,2,3},{4},{5},{6}。
从城市 1 出发到达城市 6,乘坐(1,3)(3,6)两个航班费用最大,(1,3)在国内为免费航
班, (3,6)的费用为 4,所以从 1 出发的最大费用为 4。
【数据规模】
对于 40%的数据 1<=N<=1000,1<=M<=1000
对于 100%的数据 1<=N<=20000,1<=M<=200000

分析:先用SCC缩点,然后用两次dfs求树的直径:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=4200;
int nxt[N],d[N],tot=0,head[N],vis[N],n,x,y,m;
void add(int x,int y)
{
	vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}
void dfs(int v)
{
	for(int i=head[v];i;i=nxt[i])
		if(!d[vis[i]])
		{
			d[vis[i]]=d[v]+1;
			dfs(vis[i]);
		}
}
int main()
{
	cin>>n;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	dfs(1);
	for(int i=m=1;i<=n;i++) if(d[i]>d[m]) m=i;
	memset(d,0,sizeof(d));
	dfs(m);
	for(int i=m=1;i<=n;i++) if(d[i]>d[m]) m=i;
	printf("%d",d[m]);
	return 0;
}

推论:一个点到另一个点的最长路的终点一定是树的直径的两端:
证明:
若树的直径端点为A,B 且存在点C 到点D的距离大于点C到点A或点B的距离
此时A->D 或 B->D 会成为新的直径,可以画图理解一下

代码:

#include<bits/stdc++.h>   
#define maxn 20005   
#define maxm 200005   
using namespace std;   
   
int n,m,id,dfn[maxn],low[maxn],head[maxn],head2[maxn],cnt;   
int dis[maxn],dis1[maxn],mx=0,root;   
int belong[maxn],belnum;   
bool vis[maxn];   
 stack<int> stk;   
 struct Edge{       
 int u,v,val,next;   
 }edge[maxm<<1],e[maxm<<1];   
    
 inline int read(){   
     int x=0,f=1;char c=getchar();   
     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}   
     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}   
     return x*f;   
 }   
 namespace Tarjan{    
    
 inline void add(int u,int v,int val)   
 {      
     edge[++cnt].v=v;       
     edge[cnt].u=u;     
     edge[cnt].val=val;     
     edge[cnt].next=head[u];    
     head[u]=cnt;   
 }    
    
 inline void tarjan(int u,int fa)   
 {      
     dfn[u]=low[u]=++id;    
     vis[u]=1;      
     stk.push(u);       
     for(int i=head[u];i!=-1;i=edge[i].next)    
     {      
         int v=edge[i].v;       
         if(!dfn[v])    
         {      
             tarjan(v,u);       
             low[u]=min(low[u],low[v]);     
         }      
         else if(vis[v]&&v!=fa)     
         {      
             low[u]=min(low[u],dfn[v]);     
         }      
     }      
     if(dfn[u]==low[u])     
     {      
             belnum++;      
        int temp;      
        do{    
            temp=stk.top();    
            belong[temp]=belnum;       
            vis[temp]=0;       
            stk.pop();     
        }while(temp!=u);       
    }   
}    
   
inline void solve1(){      
    memset(head,-1,sizeof(head));      
    for(int i=1,u,v,val;i<=m;i++){      
        u=read();v=read();val=read();      
        add(u,v,val);add(v,u,val);     
    }      
    for(int i=1;i<=n;i++){      
        if(!dfn[i]) tarjan(i,0);       
    }   
}    
   
}    
   
namespace LP{    
   
inline void Add(int u,int v,int val){      
    e[++cnt].v=v;      
    e[cnt].val=val;    
    e[cnt].next=head2[u];      
    head2[u]=cnt;   
}    
   
void dfs1(int u,int fa){       
    for(int i=head2[u];i!=-1;i=e[i].next)      
    {      
        int v=e[i].v;      
        if(v==fa)   continue;      
        dis[v]=dis[u]+e[i].val;    
        if(dis[v]>mx)    mx=dis[v],root=v;      
        dfs1(v,u);     
    }   
}

void dfs2(int u,int fa){       
    for(int i=head2[u];i!=-1;i=e[i].next)      
    {      
        int v=e[i].v;      
          if(v==fa)   continue;      
          dis1[v]=dis1[u]+e[i].val;      
          dfs2(v,u);     
      }   
  }    
     
  inline void solve2(){      
      cnt=0;     
      memset(head2,-1,sizeof(head2));    
      for(int i=1;i<=n;i++)       
          for(int j=head[i];j!=-1;j=edge[j].next)    
          {      
              if(belong[i]!=belong[edge[j].v])       
                  Add(belong[i],belong[edge[j].v],edge[j].val);      
          }      
      dfs1(1,-1);    
      mx=0;memset(dis,0,sizeof(dis));    
      dfs1(root,-1);     
      mx=0;      
      dfs2(root,-1);     
      for(int i=1;i<=n;i++)       
          printf("%d\n",max(dis[belong[i]],dis1[belong[i]]));   
  }    
         
  }   
  int main(){      
      n=read();m=read();     
      Tarjan::solve1();      
      LP::solve2();      
      return 0;   
  }   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设方案旨在通过融合先进技术,如物联网、大数据、人工智能等,实现校园的智能化管理与服务。政策的推动和技术的成熟为智慧校园的发展提供了基础。该方案强调了数据的重要性,提出通过数据的整合、开放和共享,构建产学研资用联动的服务体系,以促进校园的精细化治理。 智慧校园的核心建设任务包括数据标准体系和应用标准体系的建设,以及信息化安全与等级保护的实施。方案提出了一站式服务大厅和移动校园的概念,通过整合校内外资源,实现资源共享平台和产教融合就业平台的建设。此外,校园大脑的构建是实现智慧校园的关键,它涉及到数据中心化、数据资产化和数据业务化,以数据驱动业务自动化和智能化。 技术应用方面,方案提出了物联网平台、5G网络、人工智能平台等新技术的融合应用,以打造多场景融合的智慧校园大脑。这包括智慧教室、智慧实验室、智慧图书馆、智慧党建等多领域的智能化应用,旨在提升教学、科研、管理和服务的效率和质量。 在实施层面,智慧校园建设需要统筹规划和分步实施,确保项目的可行性和有效性。方案提出了主题梳理、场景梳理和数据梳理的方法,以及现有技术支持和项目分级的考虑,以指导智慧校园的建设。 最后,智慧校园建设的成功依赖于开放、协同和融合的组织建设。通过战略咨询、分步实施、生态建设和短板补充,可以构建符合学校特色的生态链,实现智慧校园的长远发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值