D. TediousLee
我们先处理一下叶子结点(ye)和1个儿子的结点(one)之间的关系
显然
找规律题 观察3号树 4号树和6号树的关系 发现4号树的叶子 在6号树变成了“爪子” 每个爪子贡献为4 然后我们去掉4号树的叶子 发现刚好得到了一棵完整的3号树
于是 猜想规律是 然后用样例验证一下就知道了
#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;
}