【数位贪心】
【数位贪心】
十进制/二进制填数字
一般是从高位到低位考虑->继承
Minimum OR Path
https://atcoder.jp/contests/abc408/tasks/abc408_e
/*【贪心】最高位为0,次高位为0,...->从高位扫到低位 并继承高位的结果
【位数】设S:S中若存在i:所存在的边,第i位一定全是0
->从高位到低位:继承上一次的S,并把当位设成1(满足条件)
->如果能跑到n:说明该位是可以的 否则ans该位设为1
*/
const int N=2e5+10;
int n,m;
vector<PII> g[N];
bool st[N];
void dfs(int u,int fa,int x){
st[u]=1;
for(auto son:g[u]){
int pos=son.first;
int val=son.second;
if(pos!=fa){ //该位及以前继承的位全为0
if(!st[pos] && !(val&x)) dfs(pos,u,x);
}
}
}
void solve(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
int s=0,ans=0;
for(int i=29;i>=0;i--){
memset(st,0,sizeof st);
dfs(1,-1,s|(1<<i));
if(st[n]) s|=(1<<i);
else ans|=(1<<i);
}
cout<<ans<<endl;
}
XOR-factorization
【经典二进制填数trick】
https://codeforces.com/contest/2180/problem/C
题目大意
给定n和k,满足\(0<=a_i<=n\),需要使得\(a_1⊕a_2⊕...⊕a_k=n\),且要使\(a_1+a_2+...+a_k=n\)最大,求序列。
思路
在可以的范围内构造尽可能多的1
若n为奇数:全部为n即可
若n为偶数:
错误贪心思路:前n-2个数全为n 第n-1和n个数拼成一个n
正确思路: 按位考虑

代码
i64 n;
int k;
void solve(){
cin>>n>>k;
if(k%2){
for(int i=1;i<=k;i++){
cout<<n<<" ";
}
cout<<endl;
}
else{
vector<i64> ans(k+1,0);
int idx=0,c=1;
for(i64 i=60;i>=0;i--){
if((n>>i)&1LL){
for(int j=1;j<=k;j++){
if(j!=c){
ans[j]+=(1LL<<i);
}
}
c=(c+1)%k;
if(c==0) c=k;
idx++;
}
else{
for(int j=1;j<=idx/2*2&&j<=k;j++){
ans[j]+=(1LL<<i);
}
}
}
for(int i=1;i<=k;i++) cout<<ans[i]<<" ";
cout<<endl;
}
}

浙公网安备 33010602011771号