D
统计子节点中1的个数即可(类似树形dp?)
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
string x;
int dp[N];
std::vector<int> v[N];
void dfs(int u,int fa){
if(x[u]=='1') dp[u]=1;
for(auto c:v[u]){
if(c==fa) continue;
dfs(c,u);
dp[u]+=dp[c];
}
}
void solve(){
int n;
cin>>n;
cin>>x;
x=","+x;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,-1);
for(int i=1;i<=n;i++){
cout<<dp[i]-(x[i]=='1')<<endl;
}
}
signed main(){
int t=1;
//cin>>t;
while(t--){
solve();
}
}
E
我们思考如果当前可以和之前的点重排成一个回文数,那么有两种情况
1.之前出现过的奇偶性质完全相等的(奇-奇=偶 偶-偶=偶)
2.之前出现过的奇偶性质中有一个不同的(奇-偶=奇 偶-奇=奇,这样会有一个值出现次数为奇数,就行 39993 393 ……)
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
void solve(){
string x;
cin>>x;
int ans=0;
map<vector<int>,int>mp;
vector<int>sum;
for(int i=0;i<10;i++) sum.push_back(0);
mp[sum]++;
for(int i=0;i<x.size();i++){
sum[x[i]-'0']^=1;
ans+=mp[sum];
for(int i=0;i<10;i++){
vector<int>tt=sum;
tt[i]^=1;
ans+=mp[tt];
}
mp[sum]++;
}
cout<<ans<<endl;
}
signed main(){
int t=1;
// cin>>t;
while(t--){
solve();
}
}
F
状态压缩dp
变成r对应0
变成e对应1
变成d对应2
可以用三进制模拟
1.首先枚举自己可行的转变的状态j
也就是,在自己这列中,相邻不相等的状态
2.然后再枚举上一列的状态k
如果对于j和k,如果不冲突则可以直接转化
最终答案就是min(dp[m-1][k])
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
string str[N];
int tmp[N];
int t[5]={1,3,9,27,81};
int dp[1010][1010];
int n,m;
int b[4];
bool check(int num){
for(int i=0;i<n;i++){
b[i]=num%3;
num/=3;
}
for(int i=1;i<n;i++) if(b[i]==b[i-1]) return false;
return true;
}
bool check(int x,int y){
for(int i=0;i<n;i++){
if(x%3==y%3) return false;
x/=3;
y/=3;
}
return true;
}
void solve(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>str[i];
int ans=1e18;
map<char,int>mp;
mp['r']=0;
mp['e']=1;
mp['d']=2;
memset(dp,0x3f,sizeof dp);
for(int i=0;i<m;i++){
for(int j=0;j<t[n];j++){
int res=0;
int now=j;
if(check(j)){
if(!i){
for(int k=0;k<n;k++){
if(mp[str[k][i]]!=(now%3))res++;
now/=3;
}
dp[i][j]=min(dp[i][j],res);
}else{
for(int k=0;k<n;k++){
if(mp[str[k][i]]!=(now%3))res++;
now/=3;
}
for(int k=0;k<t[n];k++){
if(check(j,k)){
dp[i][j]=min(dp[i][j],dp[i-1][k]+res);
}
}
}
if(i==m-1){
ans=min(dp[i][j],ans);
}
}
}
}
cout<<ans<<endl;
}
signed main(){
int t=1;
//cin>>t;
while(t--){
solve();
}
}