Codeforces Round #652 (Div. 2)

D. TediousLee

我们先处理一下叶子结点(ye)和1个儿子的结点(one)之间的关系 

显然  

ye[i]=one[i-1]*2+ye[i-1]     one[i]=ye[i-1]

找规律题  观察3号树 4号树和6号树的关系  发现4号树的叶子 在6号树变成了“爪子” 每个爪子贡献为4  然后我们去掉4号树的叶子 发现刚好得到了一棵完整的3号树

于是   猜想规律是  f[n]=f[n-3]+ye[i-2]*4 然后用样例验证一下就知道了

#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+20;
typedef long long ll;
const ll mod = 1e9+7;
ll ye[N],one[N],f[N];
int main(){
	int t;
	scanf("%d",&t);
	ye[1]=1,one[1]=0;
	for(int i = 2; i <= 2e6; i++){
		ye[i]=(one[i-1]*2ll%mod+ye[i-1])%mod;
		one[i]=ye[i-1];
	}
	f[1]=f[2]=0;
	f[3]=4;
	for(int i = 4; i <= 2e6; i++)
	f[i]=(f[i-3]+ye[i-2]*4ll%mod)%mod;
	while(t--){
		int n;
		scanf("%d",&n);
		printf("%lld\n",f[n]);
	}
	return 0;
}

E. DeadLee

设 d[i]为喜欢第i个食物的人数   w[i]和题目的意思一样 如果d[i]>w[i] 我们尚且不能确定是不是可以   但是如果d[i]<=w[i]  那么这些人无论什么时候吃 都是可以的(不会出现食物不足的情况) 鉴于次进行贪心  对于d[i]<=w[i] 的食物 我们加入队列 并且把吃这些食物的人放在最后面(因为他们一定能吃到  就让不一定能吃到的先吃)  然后对于这些人吃的另外的一种食物x 让它的d[x]--  也就是说喜欢吃这个食物的人减少一个 因为我们已经安排他吃i食物了  如果d[x]==w[x] 那么把x食物加入队列 在继续进行下去  

如果队列为空 但是我们还没有遍历n个食物的话 说明不能满足要求 输出“dead”

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define pa pair<int,int>
vector<pa>v[N];
int d[N],w[N],ans[N],vis[N];
queue<int>Q;
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++) scanf("%d",&w[i]);
	for(int i = 1; i <= m; i++){
		int x,y;
		scanf("%d%d",&x,&y);
		v[x].push_back(make_pair(y,i));
		v[y].push_back(make_pair(x,i));
		d[x]++;d[y]++; 
	} 
	for(int i = 1; i <= n; i++)
	if(d[i]<=w[i]) Q.push(i);
	int tot=m;
	for(int i = 1; i <= n; i++){
		if(Q.empty()) return puts("DEAD"),0;
		int g = Q.front();Q.pop();
		for(auto j:v[g]){
			if(vis[j.second]) continue;
			vis[j.second]=1;
			ans[tot--]=j.second;
			d[j.first]--;
			if(d[j.first]==w[j.first]) Q.push(j.first);
		}
	}
	puts("ALIVE");
	for(int i = 1; i <= m; i++) printf("%d ",ans[i]);
	puts("");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43824564/article/details/106940392