题意:求是否所有格子周围都有偶数个'o'
题解:暴力遍历即可。
题意:一个人有n个卡片,每个卡片上面有一个英文大写字母。另一个人从中取k张,每张卡片的价值是取出同种卡片的数量。
题解:统计每种卡片出现次数,排序从数量多的开始取。hack点为爆int。
题意:给出一个集合包含n个数,进行两种操作。一种是:将集合给A,集合内所有数的和加到结果中,将集合给B。另一种是:如果B接到的集合只含一个元素,丢弃。否则将集合任意分成两份,分别给A。求最大结果。
题解:画了几种情况发现每次去掉最小的结果最大。写了,过了。
代码:
题意:一棵树,顶点分为黑白两种。删去一些边,使得形成的每棵新树有且只有一个黑点。求删边的可能数。
官方题解:
Fill a DP table such as the following bottom-up:
DP[v][0] = the number of ways that the subtree rooted at vertex v has no black vertex.
DP[v][1] = the number of ways that the subtree rooted at vertex v has one black vertex.
The recursion pseudo code is folloing:
DFS(v):
DP[v][0] = 1
DP[v][1] = 0
foreach u : the children of vertex v
DFS(u)
DP[v][1] *= DP[u][0]
DP[v][1] += DP[v][0]*DP[u][1]
DP[v][0] *= DP[u][0]
if x[v] == 1:
DP[v][1] = DP[v][0]
else:
DP[v][0] += DP[v][1]
The answer is DP[root][1].
PS:当时只推出了dp[v][1] *= dp[u][0];后面说什么也没推出来,太弱啊……
代码:
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// . ' \\| |// `.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
//
// .............................................
// 佛祖保佑 永无BUG
// 佛曰:
// 写字楼里写字间,写字间里程序员;
// 程序人员写程序,又拿程序换酒钱。
// 酒醒只在网上坐,酒醉还来网下眠;
// 酒醉酒醒日复日,网上网下年复年。
// 但愿老死电脑间,不愿鞠躬老板前;
// 奔驰宝马贵者趣,公交自行程序员。
// 别人笑我忒疯癫,我笑自己命太贱;
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define clr(ar,vel) memset(ar,vel,sizeof(ar))
#define PB push_back
typedef long long ll;
const int maxint = 0x7fffffff;
const ll maxll = 1LL<<60;
const int mod = 1000000007;
const double EPS = 1e-10;
vector<int> vi[100010];
int vel[100010], vis[100010];
int dp[100010][2]; //0:不全脱离 ; 1:全脱离;
inline int dfs(int n){
// cout << n << endl;
int flag = 0;
ll zero = 1, one = 0;
for(int i = 0; i < vi[n].size(); i ++){
int nxt = vi[n][i];
if( vis[nxt] ) continue;
vis[nxt] = 1;
dfs( nxt );
one *= dp[nxt][0];
one += zero*dp[nxt][1];
zero *= dp[nxt][0];
one %= mod;
zero %= mod;
}
dp[n][0] = zero;
dp[n][1] = one;
if( vel[n]) dp[n][1] = dp[n][0];
else dp[n][0] += dp[n][1];
dp[n][1] %= mod;
dp[n][0] %= mod;
}
int main(){
int n;
cin >> n;
memset(vis, 0, sizeof(vis));
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i ++) vi[i].clear();
for(int i = 1, x; i < n; i ++){
cin >> x;
vi[x].push_back(i);
// vi[i].push_back(x); 一开始建的无向边,wa了 看人家都是有向的注销了,过了
}
for(int i = 0; i < n; i ++) cin >> vel[i];
dfs(0);
// cout << "can solve" << endl;
cout << dp[0][1]%mod << endl;
return 0;
}