1112

董神出的题目 第一次成功卡上200pts...
A 物理
问题描述
物理课上,nodgd一拍脑袋,发明了一个最短路算法:给无向图的每个节点制作一个小球,
每条边制作一根绳子,绳子的长度就是边的权值;将最短路问题的起点对应的小球缓缓提
起,然后测量每个小球到起点小球的距离,就得到了起点到每个节点的最短路。nodgd发现
这个算法非常厉害——它的时间复杂度为O(1) 。
nodgd打算在课上给大家演示这个最短路算法,于是用数据生成器生成了一组数据,即一个
个节点 条边的无向图。nodgd发现,分别选取不同的最短路起点,有些绳子总是处于松
弛状态,有些绳子总是处于绷紧状态,剩下的绳子时而绷紧时而松弛,这样可以将绳子分成
三类。现在nodgd想知道,每种绳子属于哪一类?
输入格式
输入文件phys.in。
第一行两个整数 nm,表示无向图的节点数和边数。
接下来 m行,每行三个整数 abc,表示第 i条无向边连接 ab节点,权值为 c。保证没
有重边和自环。
输出格式
输出文件phys.out。
输出 m行,第 i行输出一个整数x , 分别表示第 x根绳子总是总是松弛、总是绷
紧、时而绷紧时而松弛。
输入输出样例1
见下发的文件phys-sample1.in和phys-sample1.ans。

董神还是这么毒瘤 专门卡dij

看到\(n<=500\) 邻接存图 floyd呗 dij主要处理点多边少的情况

然后讨论每个点的情况 如果这个点处于一条边的端点 就可以讨论是否为最短距离
如果不是端点讨论边是否存在于最短路中 否则就不行
code:

//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 510
#define ll long long 
#define inf 100000000000
bool is[250010],son[250010];
struct node {
	int st,en;
	ll l;
} ed[250010];
ll mapp[maxnn][maxnn];
int n,m;
ll x,y,z;
#define GC getchar()
inline int R() {
	char t;
	int x=0;
	int f=1;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
int main() {
	freopen("phys.in","r",stdin);
	freopen("phys.out","w",stdout);
	n=R();
	m=R();
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			if(i==j) continue;
			mapp[i][j]=inf;
		}
	}
	for(int i=1; i<=m; i++) {
		ed[i].st=R();
		ed[i].en=R();
		ed[i].l=R();
		mapp[ed[i].st][ed[i].en]=mapp[ed[i].en][ed[i].st]=ed[i].l;
	}
	for(int k=1; k<=n; k++) {
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				if(mapp[i][j]>mapp[i][k]+mapp[k][j]) {
					mapp[i][j]=mapp[i][k]+mapp[k][j];
				}
			}
		}
	}
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++) {
			if(ed[j].st==i) {
				if(mapp[i][ed[j].en]==ed[j].l) {
					is[j]=true;
					continue;
				}
				continue;
			}
			if(ed[j].en==i) {
				if(mapp[i][ed[j].st]==ed[j].l) {
					is[j]=true;
					continue;
				}
				continue;
			}
			if(mapp[i][ed[j].en]+ed[j].l==mapp[i][ed[j].st]) {
				is[j]=true;
				continue;
			}
			if(mapp[i][ed[j].st]+ed[j].l==mapp[i][ed[j].en]) {
				is[j]=true;
				continue;
			}
			son[j]=true;
		}
	}
	for(int i=1; i<=m; i++) {
		if((!is[i])&&son[i]) {
			printf("1\n");
			continue;
		}
		if(is[i]&&(!son[i])) {
			printf("2\n");
			continue;
		}
		if(is[i]&&(son[i])) {
			printf("3\n");
			continue;
		}
	}
}


B. 数学
(math.c/.cpp/.in/.out)
问题描述
扎实的数学功底是每个信息学竞赛选手必须具备的基本素养之一。
比如计算一个正整数 n有多少个正约数,通常的做法是先将 n分解质因数,将每个质因数的
幂次加一之后乘起来。
现在nodgd给你一个正整数序列 i,k,并进行很多次询问:序列前 i个数的乘积有
多少个正约数的所有质因数都不超过k 呢?特别的,1 没有质因数,所以无论怎么询问 总是
符合条件。
输入格式
输入文件math.in。
第一行两个整数 ,表示序列的长度和询问的次数。
第二行 个正整数 。
从第三行起的连续 行,每行两个正整数 ,表示一次询问。
输出格式

解:
树状数组维护前缀乘积 .... 话说lhd说过可以做区间gcd 我怎么就没想到 ... 因为我打了O(sqrt(n)) 还发现自己造的极限数据跑的贼快 (sqrt(n))分解我真是厉害

一定要把自己的思路记下来 不然就会忘记自己以前想过的思路...

或者建立权值线段树 直接记一下就行了
code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxnn =1e6;
const ll  mod =998244353;
struct node {
	ll l,r,v;
} tr[maxnn];

void build(int p,int x,int y) {
	if(x==y) {
		tr[p].l=x;
		tr[p].r=y;
		tr[p].v=1;
		return ;
	} else {
		int mid=(x+y)>>1;
		build(p<<1,x,mid);
		build(p<<1|1,mid+1,y);
		tr[p].l=x;
		tr[p].r=y;
		tr[p].v=1;
	}
	tr[p].v=(tr[p<<1].v*tr[p<<1|1].v)%mod;
}
ll get(int p,int x,int y) {
	if(tr[p].l>=x&&tr[p].r<=y) {
		return tr[p].v;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	ll lll,rr;
	lll=1;
	rr=1;
	if(x<=mid) lll=get(p<<1,x,y);
	if(y>mid) rr=get(p<<1|1,x,y);
	return (lll*rr)%mod;
}
void add(int p,int x,int d) {
	if(tr[p].l==tr[p].r) {
		tr[p].v++;
		return ;
	} else {
		int mid=(tr[p].l+tr[p].r)>>1;
		if(x<=mid)add(p<<1,x,d);
		else if(x>mid) add(p<<1|1,x,d);
		tr[p].v=(tr[p<<1].v*tr[p<<1|1].v)%mod;
		return ;
	}
}
ll phi[maxnn],is[maxnn],len;
void init() {
	for(int i=2; i<=1e5+100; i++) {
		if(!is[i]) {
			phi[++len]=i;
		}
		for(int j=1; j<=len&&(phi[j]*i<=1e5+100); j++) {
			is[phi[j]*i]=1;
			if(i%phi[j]==0) break;
		}
	}
}

ll a[maxnn];
ll res[maxnn];
ll p,n,q;
struct nodee {
	ll id,pos,v;
} ans[maxnn];
bool cmp(nodee a,nodee b) {
	return a.pos<b.pos;
}
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline ll R() {
	char t;
	ll x=0;
	int f=1;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
void fen(int v) {
	ll tmp=a[v];
	for(ll i=1; (i<=len)&&(phi[i]<=sqrt(a[v])); i++) {
		if(tmp%phi[i]==0) {
			while(tmp%phi[i]==0) {
				add(1,phi[i],1);
				tmp/=phi[i];
			}
		}
	}
	if(tmp>1) {
		add(1,tmp,1);
	}
}
ll s[maxnn];
int main() {
	init();
	n=R();
	q=R();
	build(1,1,100100);
	for(int i=1; i<=n; i++) {
		a[i]=R();
	}
	for(int i=1; i<=q; i++) {
		ans[i].pos=R();
		ans[i].v=R();
		ans[i].id=i;
	}
	sort(ans+1,ans+1+q,cmp);
	int j=0;
	for(int i=1; i<=q; i++) {
		while((j<=n)&&(j<ans[i].pos)) {
			j++;
			fen(j);
		}
		ll aa=1;
		aa=get(1,1,ans[i].v);
		s[ans[i].id]=aa%mod;
	}
	for(int i=1; i<=q; i++) {
		printf("%lld\n",s[i]%mod);
	}
}

C.生物
(biol.c/.cpp/.in/.out)
问题描述
一个生态系统中有 种生物,它们形成了食物链和食物网。这 种生物中,一些是生产者,
不需要吃其他生物就能生存;剩下的一些是消费者,必须吃其他的一些生物才能生存。
一种生物的重要性定义为,如果这种生物灭绝,将会导致包括自身在内的多少种生物灭绝。
一种消费者生物,如果它的所有食物都灭绝,则这种生物也会灭绝。
一种生物的后效性定义为,如果这种生物灭绝,引发的灭绝事件将会持续多少个单位时间。
一种消费者生物,如果它的最后一种食物在上个单位时间灭绝,则它会在当前这个单位时间
灭绝。
现在的任务是计算每种生物的重要性和后效性。
输入格式
输入文件biol.in。
第一行两个整数 n,m,表示生物的种类数和食物关系数量。
接下来m 行,每行两个整数 a,b,表示第 a种生物可以以第b 种生物为食。保证不会出现
任何一种生物直接或间接吃自己的情况,同一条关系保证不会重复出现。不吃其他任何生物
的生物都是生产者。
输出格式
输出文件biol.out。
输出n 行,第i 行两个整数 c d,分别是表示第 种生物的重要性和后效性。
输入输出样例1
见下发的文件biol-sample1.in和biol-sample1.ans。

posted @ 2019-11-12 12:19  ALEZ  阅读(289)  评论(0编辑  收藏  举报