期望得分 200 实际得分160 naiive
A组队参赛
时间限制 : - MS 空间限制 : - KB
评测说明 : 1s,256m
问题描述
一年一度的ioiAKer大赛即将来临,何老板打算让信竞队的同学们组队参赛。信竞队共n名队员,他们的CF积分分别是1、2、3、...... 、n,CF积分体现了选手的能力水平,积分越高,能力越强。
按照赛会方的要求,每个学校只能派两只队伍参赛,分别对应提高组和提高组。为体现不同组别能力的区分度,要求提高组队伍中积分最低的选手必须大于普及组队伍中积分最高的选手。每组队伍的参赛人数不能为0。
何老板想知道,总共有多少种合法的组队方案。结果可能很大,mod m后再输出。
解:
定一个变量 推公式即可
注意使用ksc
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
inline ll Mod(ll a)
{
return a>=m?a%m:a;
}
inline void swap(ll a,ll b)
{
ll t=a;
a=b;
b=t;
}
inline ll ksc(ll a,ll b)
{
if(b>a)swap(a,b);
ll ans=0;
while(b)
{
if(b&1)ans=Mod(ans+a);
b>>=1;
a=Mod(a+a);
}
return ans;
}
inline ll ksm(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ksc(ans,a);
b>>=1;
a=ksc(a,a);
}
return ans;
}
int main()
{
cin>>n>>m;
cout<<((ksc(n,ksm(2,n-1))-ksm(2,n)+1)%m+m)%m;
}
B边陲防务
时间限制 : 10000 MS 空间限制 : - KB
评测说明 : 1s,256m
问题描述
何老板穿越到了古代,被封为“标记大将军”,负责某边关地区的防务。
该地区有n座城,编号1到n。城间通过m条双向马路相连,每条马路都有一定的长度。其中有k座城是军事要塞,驻扎有军队。
何将军规定,一旦某个要塞发生战事,与它距离最近的要塞必须立即派兵支援。何老板想知道,每座要塞与离它最近的一个要塞的距离有多远,请你帮他计算一下。
解:
挺好的一道最短路的题目
首先这道题肯定是最短路
但是最短路不能跑多次
假设只跑一次 怎么办??
注意到最短路一般是单源最短路
所以我们应该建立一个超级源点 将其连相要塞点
然后你就会注意到** 你已经求出了每个要塞点到非要塞点的最短路径**
然后就可以设一个p数组 定义为每个点与其最近 的要塞点的 编号 初始的时候每个要塞点进队
然后你就可以枚举每条边 起始点走的一定是最短路 假如p的值不一样 就更新答案
code:
spfa 版本
//
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define maxnn 1000010
#define inf 100000000
#define ll long long
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
ll n,m,k;
ll las[maxnn],en[maxnn],le[maxnn],nex[maxnn],tot;
ll dis[maxnn];
int kk[maxnn];
int mask[maxnn];
int p[maxnn];
int mark[maxnn];
struct node {
ll st,e,l;
} ed[maxnn];
ll ans[maxnn];
int cnt=0;
inline ll R()
{
char t;
ll x=0;
t=GC;
while(!isdigit(t)) t=GC;
while(isdigit(t))
{
x=x*10+t-'0';
t=GC;
}
return x;
}
void add(ll a,ll b,ll c) {
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
le[tot]=c;
}
void spfa() {
queue<int > Q;
for(int i=1; i<=n; i++) {
dis[i]=inf;
mark[i]=0;
if(mask[i])
{Q.push(i);
dis[i]=0;
p[i]=i;}
}
while(Q.size()) {
int v=Q.front();
Q.pop();
mark[v]=0;
for(int i=las[v]; i; i=nex[i]) {
int u=en[i];
if(dis[u]>dis[v]+le[i]) {
if(mask[u])
p[u]=u;
else
p[u]=p[v];
dis[u]=dis[v]+le[i];
if(!mark[u]) {
mark[u]=1;
Q.push(u);
}
}
}
}
}
int main() {
ll x,y,z;
n=R();
m=R();
k=R();
for(int i=1;i<=n+100;i++)
{
ans[i]=inf;
}
for(int i=1; i<=m; i++) {
x=R();
y=R();
z=R();
add(y,x,z);
add(x,y,z);
ed[++cnt].st=x;
ed[cnt].e=y;
ed[cnt].l=z;
}
for(int i=1; i<=k; i++) {
kk[i]=R();
mask[kk[i]]=1;
}
spfa();
for(int i=1; i<=m; i++) {
if(p[ed[i].st]!=p[ed[i].e]) {
ll tmp1=dis[ed[i].st]+dis[ed[i].e]+ed[i].l;
ans[p[ed[i].st]]=min(ans[p[ed[i].st]],tmp1);
ans[p[ed[i].e]]=min(ans[p[ed[i].e]],tmp1);
}
}
for(int i=1; i<=k; i++) {
if(ans[kk[i]]>=inf)
{
printf("-1 ");
}
else
printf("%lld ",ans[kk[i]]);
}
}
dij 版本
//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 2000010
#define maxn 501000
#define inf 100000000
#define ll long long
typedef pair<long long,int > P;
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
ll n,m,k;
ll las[maxnn],en[maxnn],le[maxnn],nex[maxnn],tot;
ll dis[maxn];
int kk[maxn];
int mask[maxn];
int p[maxn];
int mark[maxn];
struct node {
ll st,e,l;
} ed[maxn];
ll ans[maxn];
int cnt=0;
inline ll R()
{
char t;
ll x=0;
t=GC;
while(!isdigit(t)) t=GC;
while(isdigit(t))
{
x=x*10+t-'0';
t=GC;
}
return x;
}
void add(ll a,ll b,ll c) {
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
le[tot]=c;
}
priority_queue<P,vector<P>,greater<P> > Q;
void dij() {
for(int i=1; i<=n+1; i++) {
dis[i]=inf;
mark[i]=0;
}
dis[n+1]=0;
Q.push(make_pair(0,n+1));
while(Q.size()) {
P v=Q.top();
Q.pop();
if(dis[v.second]!=v.first)continue;
for(int i=las[v.second]; i; i=nex[i]) {
int u=en[i];
if(dis[u]>dis[v.second]+le[i]) {
if(mask[u])
p[u]=u;
else
p[u]=p[v.second];
dis[u]=dis[v.second]+le[i];
Q.push(make_pair(dis[u],u));
}
}
}
}
int main() {
ll x,y,z;
n=R();
m=R();
k=R();
for(int i=1;i<=n+100;i++)
{
ans[i]=inf;
}
for(int i=1; i<=m; i++) {
x=R();
y=R();
z=R();
add(y,x,z);
add(x,y,z);
ed[++cnt].st=x;
ed[cnt].e=y;
ed[cnt].l=z;
}
for(int i=1; i<=k; i++) {
kk[i]=R();
mask[kk[i]]=1;
add(kk[i],n+1,0);
add(n+1,kk[i],0);
}
dij();
for(int i=1; i<=m; i++) {
if(p[ed[i].st]!=p[ed[i].e]) {
ll tmp1=dis[ed[i].st]+dis[ed[i].e]+ed[i].l;
ans[p[ed[i].st]]=min(ans[p[ed[i].st]],tmp1);
ans[p[ed[i].e]]=min(ans[p[ed[i].e]],tmp1);
}
}
for(int i=1; i<=k; i++) {
if(ans[kk[i]]>=inf)
{
printf("-1 ");
}
else
printf("%lld ",ans[kk[i]]);
}
}
C桥梁项目
时间限制 : - MS 空间限制 : - KB
评测说明 : 2s,256m
问题描述
有一个岛国,由n个小岛构成,岛屿编号1到n。该国需要建立一些桥梁,将n个岛屿连接起来。 何老板打算承包该桥梁项目。根据实地考察,他为该国制定了一个建桥计划:通过建立n-1座双向桥,就可将所有岛屿连接,并保证任意两座小岛都可互通。 何老板向该国政府给出了他的详细计划,即n-1座桥分别连接那两个岛屿。但是该桥梁项目耗资巨大,该国无力承担。于是,该国政府提出一个折中方案:将原计划的n-1座双向桥,改为建n-1座单向桥,只需保证指定的m对重要岛屿“可通”即可。所谓“可通”是指,对于给定的每一对岛屿(X,Y),存在一条从X到Y的路径或者从Y到X的路径即可。 这下难到了何老板,他想计算出满足条件的方案有多少种,再从中选择最优方案。请你帮忙计算出所有的方案数。 简单说:何老板要你建设n-1座单向桥,桥的方向性由你来设定,使得指定岛屿可通。要求总的方案数。
sol:
首先答案肯定是(2^i) 次方
然后就可以考虑路径问题
路径只有同向或者反向两种状况
然后你就会想到并查集 维护集合的同向或者反向的状态
记录w[x]1 表示为反向
w[x]0 表示同向
每次对于一条路径 首先在lca-1层合并点并且标记为0
然后对于操作 每次找到x和y的集合 如果在一个集合 就判断是否为同向 如果为同向就不能转折
否则就可以转折
code:
//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define maxnn 700000
int las[maxnn],en[maxnn],nex[maxnn],tot;
int f[maxnn];
int dep[maxnn];
int ff[maxnn][30];
int ttt=0;
int w[maxnn];
int p[maxnn][5];
int n,m;
#define GC getchar()
void add(int a,int b)
{
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
}
inline ll R()
{
char t;
ll x=0;
t=GC;
while(!isdigit(t)) t=GC;
while(isdigit(t))
{
x=x*10+t-'0';
t=GC;
}
return x;
}
int gf(int v){
if(f[v]==v)
{
return v;
}
else{
int tmp=f[v];
f[v]=gf(f[v]);
w[v]^=w[tmp];
return f[v];
}
}
int go_up(int s,int k)
{
int o=log2(n);
for(int i=o;i>=0;i--)
{
if(k&(1<<i))
{
s=ff[s][i];
}
}
return s;
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
x=go_up(x,dep[x]-dep[y]);
if(x==y) return y;
int s=log2(n);
for(int i=s;i>=0;i--)
{
if(ff[x][i]!=ff[y][i])
{
x=ff[x][i];
y=ff[y][i];
}
}
return ff[x][0];
}
void dfs(int v,int fa)
{
ff[v][0]=fa;
dep[v]=dep[fa]+1;
int s=log2(n);
for(int i=1;i<=s;i++)
{
ff[v][i]=ff[ff[v][i-1]][i-1];
}
for(int i=las[v];i;i=nex[i])
{
int u=en[i];
if(u!=fa)
{
dfs(u,v);
}
}
}
ll ksm(ll a,ll b)
{
a%=mod;
ll ans=1;
while(b)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans%mod;
}
void to(int x,int y)
{
x=gf(x);
while(dep[x]-2>=dep[y])
{
int k=ff[x][0];
k=gf(k);
f[x]=k;
x=gf(x);
}
}
int main()
{
n=R();
m=R();
int x,y;
for(int i=1;i<n;i++)
{
x=R();
y=R();
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
f[i]=i;
}
dfs(1,0);ff[1][0]=1;
for(int i=1;i<=m;i++)
{
x=R();
y=R();
int lc=lca(x,y);
to(x,lc);to(y,lc);
p[i][0]=x;
p[i][1]=y;
p[i][2]=lc;
}
for(int i=1;i<=m;i++)
{
if((p[i][0]==p[i][2])||(p[i][1]==p[i][2]))
{
continue;
}
int u=gf(p[i][0]);
int v=gf(p[i][1]);
if(u==v)
{
if((w[p[i][0]]^w[p[i][1]])!=1)
{
puts("0");
return 0;
}
continue;
}
else
{
f[u]=v;
w[u]=1^w[p[i][0]]^w[p[i][1]];
}
}
int ans=1;
for(int i=2;i<=n;i++)
{
gf(i);
if(f[i]==i)
{
ans=(ans*2)%mod;
}
}
printf("%d",ans);
}