按照题意模拟即可,每两项插入0,特判null节点   ListNode* insert0(ListNode* head) {        ListNode* ret=head;        while(head){            ListNode* nxt=head->next;            ListNode* p=new ListNode(0);            if(nxt!=nullptr){                head->next=p;                p->next=nxt;            }            head=nxt;        }        return ret;    }构造,可以知道最后一层节点有 \frac{2}{n-1},则根节点权值给\frac{2}{n-1} 往下递归时,子节点值为根节点/2即可  void dfs(int d,TreeNode* cur,int n){        if(d==n) return;        cur->left=new TreeNode((cur->val)/2);        cur->right=new TreeNode((cur->val)/2);        dfs(d+1,cur->left,n);        dfs(d+1,cur->right,n);     }    TreeNode* create(int n) {        TreeNode* root=new TreeNode(1<<(n-1));        dfs(1,root,n);        return root;    }先算出R的所有和,若为奇数,则需要在没染色的奇数格子里选奇数个方块,假设有odd个,方案数有C(odd,1)+C(odd,3)+...,偶数格子里任选,每个格子选和不选两种情况,方案数为qmi(2,even),两者相乘即可,若为偶数,则奇数方案数为C(odd,0)+C(odd,2)+...,偶数任选,两者相乘 typedef long long ll;     const ll N=2e5+10;     ll a[200005],cnt=0,mod=1e9+7;     ll fact[200005],inv[200005];    int getMethod(ListNode* head, string colors) {        // write code here        ListNode* cur=head;        while(cur){            a[cnt++]=cur->val;            cur=cur->next;        }        fact[0]=inv[0]=1;        for(ll i=1;i<=cnt;i++){            fact[i]=fact[i-1]*i%mod;            inv[i]=qmi(fact[i],mod-2,mod)%mod;        }        ll s=0,odd=0,even=0;        for(ll i=0;i<cnt;i++){            if(colors[i]=='R') s+=a[i];            else{                odd+=(a[i]&1);                even+=(a[i]%2==0);            }        }       // cout<<s<<" "<<odd<<" "<<even<<endl;        if(s&1){            if(odd){                ll ans=1,res=0;                for(int i=1;i<=odd;i+=2){                    res=(res+C(odd,i))%mod;                }                ans=res*qmi(2,even,mod)%mod;                return ans;            }            else return 0;        }else{            cout<<s<<" "<<odd<<" "<<even<<endl;            ll ans=1;            ll res=0;            for(int i=0;i<=odd;i+=2){                res=(res+C(odd,i))%mod;            }            ans=res*qmi(2,even,mod)%mod;            cout<<ans<<endl;            return ans;        }    }    ll C(ll x,ll y){        return (((fact[x]*inv[y])%mod)*inv[x-y])%mod;    }    ll qmi(ll x,ll y,ll mod){        ll res=1;        while(y){            if(y&1) res=res*x%mod;            y>>=1;            x=x*x%mod;        }        return res;    }二分答案最后的最小连续1长度x是多少,问题转化为把一段连续1,转化成1连续长度不超过x,那么假设这段1长度为len,每x+1个1,就需要变1个0,分隔开他们,所以贡献值是len/(x+1),累加所有的len长度,判断贡献值和sum是否<=题目给出的最大操作数k即可bool check(string& s,int x,int k){        int res=0;        for(int i=0;i<s.size();i++){            int j=i;            if(s[i]=='1'){                int j=i;                while(j+1<s.size()&&s[j+1]=='1'){                    j++;                }                int len=j-i+1;                if(len>x){                    res+=len/(x+1);                }                i=j;            }        }        cout<<x<<" "<<res<<" "<<k<<endl;        return res<=k;    }    int maxLen(string s, int k) {        // write code here        int l=0,r=s.size();        while(l<r){            int mid=l+r>>1;            if(check(s,mid,k)) r=mid;            else l=mid+1;        }        return l;    }
点赞 9
评论 2
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务