noip模擬42(待補)
阿新 • • 發佈:2021-08-19
A. 卷
樹形\(dp\),用對數輔助取模權值的比較.
A_code
#include<bits/stdc++.h> using namespace std; namespace BSS { #define ll long long int #define re register ll #define lf double #define lbt(x) (x&(-x)) #define lb lower_bound #define ub upper_bound #define mp make_pair #define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout) #define Fill(x,y) memset(x,y,sizeof x) #define Copy(x,y) memcpy(x,y,sizeof x) inline ll read() { ll ss=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); return cit?ss:-ss; } } using namespace BSS; const ll N=2e5+51,mod=1e9+7; ll n,ts; ll head[N],val[N]; struct I { lf lg; ll w=1,vis; } f[N][2]; struct II { ll u,v,nxt; } e[N<<1]; inline I getmax(I i,I j){ return i.lg>j.lg ? i : j ; } inline void add(ll u,ll v){ e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u], head[u]=ts; } I dfs(ll now,ll dad,bool can){ I temp; if(can){ if(f[now][1].vis) return getmax(f[now][0],f[now][1]); f[now][1].lg=log(val[now]),f[now][1].w=val[now],f[now][1].vis=1; for(re i=head[now];i;i=e[i].nxt){ if(e[i].v==dad) continue; temp=dfs(e[i].v,now,0); f[now][1].lg+=temp.lg,(f[now][1].w*=temp.w)%=mod; } if(!f[now][0].vis){ f[now][0].lg=0,f[now][0].w=1,f[now][0].vis=1; for(re i=head[now];i;i=e[i].nxt){ if(e[i].v==dad) continue; temp=dfs(e[i].v,now,1); f[now][0].lg+=temp.lg,(f[now][0].w*=temp.w)%=mod; } } return getmax(f[now][0],f[now][1]); } else{ if(f[now][0].vis) return f[now][0]; f[now][0].lg=0,f[now][0].w=1,f[now][0].vis=1; for(re i=head[now];i;i=e[i].nxt){ if(e[i].v==dad) continue; temp=dfs(e[i].v,now,1); f[now][0].lg+=temp.lg,(f[now][0].w*=temp.w)%=mod; } return f[now][0]; } } signed main(){ n=read(); ll u,v; for(re i=1;i<=n;++i) val[i]=read(); for(re i=2;i<=n;++i) u=read(),v=read(),add(u,v),add(v,u); printf("%lld",dfs(1,0,1).w%mod); return 0; }
B. 簡單題
一道確實很簡單的題..
友情提醒,以後遇到\(1\)左移多少位的數,一定要記得看範圍,看是否寫成\(1ll<<x\)..
能用快速冪儘量用快速冪,因為這個更保險,但是要注意時間.
考場程式碼加了\(ll\)就切了,懶得寫題解了.
B_code
#include<bits/stdc++.h> using namespace std; namespace BSS { #define ll long long int #define re register ll #define ull unsigned ll #define lf double #define lb lower_bound #define ub upper_bound #define mp make_pair #define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout) #define Fill(x,y) memset(x,y,sizeof x); #define Copy(x,y) memcpy(x,y,sizeof x); inline ll read() { ll ss=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); return cit?ss:-ss; } } using namespace BSS; const ll N=801; const ll mod=10000019; ll m,n,Q,bss,lmt,r,ans,sp=1; ll add[mod+10]; ll f[N][2]; inline ll ksm(ll a,ll b,ll c){ a%=c; ll temp=1; while(b){ if(b&1) temp=(temp*a)%c; a=(a*a)%c; b>>=1; } return temp%c; } inline void Pre(){ add[0]=1; for(ll i=1;i<=mod;i++) add[i]=(add[i-1]*i)%mod; } inline ll C(ll a,ll b){ if(a>b) return 0; if(!a) return 1; return (add[b]*ksm(add[a],mod-2,mod)%mod)*ksm(add[b-a],mod-2,mod)%mod; } ll lucas(ll a,ll b){ if(!a) return 1; return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod; } signed main(){ n=read(),Q=read(); Pre(); ll temp=0,temp1=0,temp2=0,temp3=0,c=0; for(ll i=log2(n);i>=0;i--){ c=n/(1ll<<i),c=(c+1)>>1ll; // 有 C 個奇數可以滿足 去重 temp3=c,c-=temp,temp=temp3; temp1=i>>1ll,temp2=(i+1)>>1ll; if(temp1==temp2) (f[temp2+1][1]+=c)%=mod; else (f[temp2][0]+=c)%=mod; } for(re i=1;i<=log2(n);i++){ (bss+=(f[i][0]*i%mod+f[i+1][1]*i%mod)%mod)%=mod; sp=(sp*(ksm(2,f[i][0],mod)%mod))%mod; } lmt=n-bss,r=lmt-bss; while(Q--){ m=read(); if(m<bss or m>lmt) { puts("0"); continue; } ans=sp*lucas(m-bss,r)%mod; printf("%lld\n",ans); } return 0; }
C. 粉絲
計數常用的兩種\(dp\),在這道題種被用得活靈活現.
C_code
#include<bits/stdc++.h> using namespace std; namespace BSS { #define ll long long int #define re register ll #define lf double #define lbt(x) (x&(-x)) #define lb lower_bound #define ub upper_bound #define mp make_pair #define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout) #define Fill(x,y) memset(x,y,sizeof x) #define Copy(x,y) memcpy(x,y,sizeof x) inline ll read() { ll ss=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); return cit?ss:-ss; } } using namespace BSS; const ll N=1e5+51; ll m,n,l,r,mod; ll f[N],g[N],sum[N]; inline ll Work(ll x){ if(x>n) return 0; Fill(f,0),Fill(g,0),Fill(sum,0); ll B=sqrt(n); B=max(B,x); f[0]=1,g[0]=1,sum[0]=1; for(re i=x;i<B;i++) for(re j=i;j<=n;j++) f[j]=(f[j]+f[j-i])%mod; ll temp,ans=0; for(re i=1;i<=n/B;i++){ temp=i*B; for(re j=i;j<=n-temp;j++) g[j]=(g[j]+g[j-i])%mod; for(re j=0;j<=n-temp;j++) sum[j+temp]=(sum[j+temp]+g[j])%mod; } for(re i=0;i<=n;i++) (ans+=sum[n-i]*f[i]%mod)%=mod; return ans; } signed main(){ l=read(),r=read(),n=read(),mod=read(); printf("%lld",(Work(l)-Work(r+1)+mod)%mod); return 0; }