P7717-「EZEC-10」序列【Trie】
生活随笔
收集整理的這篇文章主要介紹了
P7717-「EZEC-10」序列【Trie】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P7717
題目大意
求有多少個長度為nnn的序列aaa滿足,都在[0,k][0,k][0,k]的范圍內且滿足mmm個限制刑如:axxoray=za_x\ xor\ a_y=zax??xor?ay?=z
0≤n,m≤5×105,0≤k<2300\leq n,m\leq 5\times 10^5,0\leq k<2^{30}0≤n,m≤5×105,0≤k<230
解題思路
首先假設有合法方案,那么對于一個位置axa_xax?確定之后與它直接或間接限制的aya_yay?都將被確定。
我們可以設限制為一條邊,然后先dfsdfsdfs判斷一次是否限制之間沒有沖突。
然后考慮對于每個聯通塊我們隨意找到一個位置xxx,那么其他的點都將被表達為axxorwa_x\ xor\ wax??xor?w的形式。
然后我們要求找到有多少個axa_xax?滿足對于所有的www都有axxorw≤ka_x\ xor\ w\leq kax??xor?w≤k。
這個可以用TrieTrieTrie數來做,每次封閉的是一個子樹,直接處理就好了。
時間復雜度O(nlog?k)O(n\log k)O(nlogk)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define ll long long using namespace std; const ll N=5e5+10,P=1e9+7; struct node{ll to,next,w; }a[N<<1]; ll n,m,k,tot,ls[N],z[N]; ll cnt,t[N][2],res,ans=1; bool v[N];stack<ll > s; void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;return; } bool dfs(ll x){v[x]=1;s.push(z[x]);for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(v[y]){if((z[x]^a[i].w)!=z[y])return 1;}else{z[y]=z[x]^a[i].w;if(dfs(y))return 1; }}return 0; } void Limit(ll &x,ll w,ll p){if(x==-1||p<0)return;if(!x){x=++cnt;t[x][0]=t[x][1]=0;}if((k>>p)&1)Limit(t[x][(w>>p)&1^1],w,p-1);else{t[x][(w>>p)&1^1]=-1;Limit(t[x][(w>>p)&1],w,p-1);}return; } void Count(ll x,ll L,ll R){if(L>k)return;if(x==-1)res-=min(R,k)-L+1;if(x<=0)return;ll mid=(L+R)>>1;Count(t[x][0],L,mid);Count(t[x][1],mid+1,R);return; } signed main() {scanf("%lld%lld%lld",&n,&m,&k);for(ll i=1;i<=m;i++){ll x,y,w;scanf("%lld%lld%lld",&x,&y,&w);addl(x,y,w);addl(y,x,w);}res=0;for(ll i=1;i<=n;i++){if(v[i])continue;cnt=t[0][0]=0;if(dfs(i))return puts("0")&0;while(!s.empty())Limit(t[0][0],s.top(),29),s.pop();res=k+1;Count(1,0,(1<<30)-1);ans=ans*res%P;}printf("%lld\n",ans);return 0; }總結
以上是生活随笔為你收集整理的P7717-「EZEC-10」序列【Trie】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单体便利店收银系统怎么选单体便利店收银系
- 下一篇: 电脑键盘F1到F12的正确用法如何用键盘