傳送門c++
咕咕優化
typedef long long ll; int a1,a2,n,d;ll res; int main(){ scanf("%d%d%d",&a1,&a2,&n); d=a2-a1; res=1ll*(a1+a1+1ll*(n-1)*d)*n>>1; printf("%lld\n",res); return 0; }
不難發現答案要麼是\(1\)要麼是\(2\)ui
當且僅當\(k+1\)是個質數且範圍內爲\(k+1\)的倍數的數只有一個時,答案爲\(1\)不然爲\(2\)spa
聽說\(n=2\)要特殊考慮,我是直接把\(n\leq 100\)的狀況用暴力跑了code
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; typedef long long ll; ll n,k; inline bool ck(R ll x){fp(i,2,sqrt(x))if(x%i==0)return false;return true;} int vis[105]; void solve(){ R int p=1; vis[k+1]=1; fp(res,1,2333){ fp(i,2,n+1)if(vis[i]==res) fp(j,2,n+1)if(!vis[j]) if(__gcd(i,j)==1)vis[j]=res+1,++p; if(p==n)return printf("%d\n",res),void(); } } int main(){ scanf("%lld%lld",&n,&k); if(n<=100)return solve(),0; puts(ck(k+1)&&(k+1)*2>n+1?"1":"2"); return 0; }
二分+點分get
二分最遠的距離,同時強制點分中心必選,且以點分中心爲根it
那麼一個點會被選,當且僅當它的子樹中有點被選,或者它的子樹中離他最遠的點到他的距離\(=mid\)(即二分出的最遠距離),若是選的點數小於等於\(k\)說明合法class
由於點分的時候會刪點,因此記得處理來自刪點後的子樹內的最遠距離test
ps:聽說這題直接倍增就能夠過了循環
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int N=5e5+5; struct eg{int v,nx;}e[N<<1];int head[N],tot; inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int sz[N],son[N],vis[N],ok[N],dis[N],las[N],rt,size; int l,r,mid,ans,n,k,sum;bool fl; inline int max(R int x,R int y){return x>y?x:y;} void findrt(int u,int fa){ sz[u]=1,son[u]=0; go(u)if(!vis[v]&&v!=fa)findrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]); cmax(son[u],size-sz[u]); if(son[u]<son[rt])rt=u; } void did(int u,int fa){ ok[u]=0,dis[u]=las[u]; go(u)if(!vis[v]&&v!=fa)did(v,u),cmax(dis[u],dis[v]+1),ok[u]|=ok[v]; ok[u]|=(dis[u]>=mid),sum+=ok[u]; } void solve(int u){ vis[u]=1,sum=0; did(u,0); if(!ok[u])ok[u]=1,++sum; if(sum<=k)return fl=1,void(); R int t1=0,t2=0,to=0; go(u)if(!vis[v]){ if(dis[v]+1>=t2)t1=t2,t2=dis[v]+1,to=v; else cmax(t1,dis[v]+1); } if(las[u]>=t2)t1=t2,t2=las[u],to=0; else cmax(t1,las[u]); R int ss=size; go(u)if(!vis[v]){ las[v]=v==to?t1+1:t2+1; if(las[v]>mid)continue; rt=0,size=sz[v]>sz[u]?size-sz[u]:sz[v],findrt(v,0),solve(rt); if(fl)return; } } int ck(){ memset(las,0,(n+1)<<2); memset(vis,0,(n+1)<<2); fl=0,son[0]=n+1; size=n,rt=0,findrt(1,0),solve(rt); return fl; } int main(){ scanf("%d%d",&n,&k); for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u); int l=1,r=n; while(l<=r){ mid=(l+r)>>1; ck()?(ans=mid,r=mid-1):l=mid+1; } printf("%d\n",ans); return 0; }
考慮跳兒子的過程,若是是跳到一個輕兒子,那麼子樹大小減半,因此跳輕兒子的總次數不會超過\(O(log n)\)次,因此咱們只須要考慮優化跳重兒子的過程便可
對於每個點,咱們記錄它的重兒子在它的兒子中標號是多少,那麼跳重兒子的話只要計算它的重鏈和\(a_i\)的\(LCP\)便可,能夠用二分+\(Hash\)求出
複雜度\(O(n\log^2 n)\)
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int C=-1,Z=0; inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} void print(R int x){ if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]='\n'; } const int N=5e5+5; typedef unsigned long long ll; vector<int>to[N];ll bas[N]; int n,q,m; struct Bit{ ll c[N]; inline void upd(R int x,R ll y){y*=bas[x];for(;x<=N-5;x+=x&-x)c[x]+=y;} inline ll query(R int x){R ll res=0;for(;x;x-=x&-x)res+=c[x];return res;} inline ll query(R int l,R int r){return (query(r)-query(l-1))*bas[N-5-l];} }T,G; int sz[N],son[N],id[N],ed[N],dfn[N],rk[N],fa[N],a[N],deg[N],tim,rt; void dfs1(int u){ sz[u]=1,sort(to[u].begin(),to[u].end()); R int c=0; for(auto v:to[u]){ ++c,dfs1(v),sz[u]+=sz[v]; if(sz[v]>sz[son[u]])son[u]=v,id[u]=c; } } void dfs2(int u){ dfn[u]=++tim,rk[tim]=u,ed[u]=u; if(!son[u])return T.upd(tim,-23333),void(); dfs2(son[u]),ed[u]=ed[son[u]],T.upd(dfn[u],id[u]); for(auto v:to[u])if(v!=son[u])dfs2(v); } inline int min(R int x,R int y){return x<y?x:y;} int LCP(R int li,R int ri,R int l,R int r){ int lp=1,rp=min(r-l+1,ri-li+1),ans=0,mid; while(lp<=rp){ mid=(lp+rp)>>1; T.query(li,li+mid-1)==G.query(l,l+mid-1)?(ans=mid,lp=mid+1):rp=mid-1; } return ans; } int solve(R int u,R int l,R int r){ R int li=dfn[u],ri=dfn[ed[u]]; while(233){ R int len=LCP(li,ri,l,r); li+=len,l+=len; u=rk[li]; if(l>r||deg[u]<a[l])return u; u=to[u][a[l]-1],li=dfn[u],ri=dfn[ed[u]],++l; if(l>r)return u; } } int main(){ // freopen("testdata.in","r",stdin); n=read(),m=read(),q=read(); bas[0]=1;fp(i,1,N-5)bas[i]=bas[i-1]*19260817; fp(i,1,n){ fa[i]=read(); if(fa[i])to[fa[i]].push_back(i),++deg[fa[i]];else rt=i; } dfs1(rt),dfs2(rt); fp(i,1,m)a[i]=read(),G.upd(i,a[i]); for(R int op,x,y,z;q;--q){ op=read(),x=read(),y=read(); if(op==2)G.upd(x,y-a[x]),a[x]=y; else z=read(),print(solve(x,y,z)); } return Ot(),0; }
用原根預處理以後\(O(1)\)計算\(i^i\),同時直接暴力合併路徑計算答案便可,具體細節看代碼
而後是關於複雜度的問題,若\(u\)爲其中一個點,且\(u\)到某個葉子的路徑上的點分別爲\(u,p_1,p_2,p_3,...,p_x\),那麼路徑\((u,u),(u,p_1),(u,p_2),...,(u,p_x)\)中,不一樣的\(\&\)值只有\(O(\log a_i)\)種,因此假設是一條鏈,且以其中一個葉子爲根,那麼每一次把子樹裏的全部形如\((v,i)\)的路徑變成\((u,i)\)的複雜度是\(O(\log a_i)\),那麼記\(d\)爲葉子個數,在不合並路徑的狀況下複雜度爲\(O(nd\log a_i)\)
對於路徑的合併,兩個葉子只會在它們的\(LCA\)處被合併一次,因此這部分複雜度爲\(O(d^2\log^2 a_i)\),而後又由於路徑總數是\(O(n^2)\),且根據不等式\(\min(a,b)\leq \sqrt{ab}\),因此\(\min(d^2\log^2 a_i,n^2)\leq O(nd\log a_i)\)
綜上覆雜度複雜度爲\(O(nd\log a_i)\)
//quming #include<bits/stdc++.h> #define R register #define pb push_back #define fi first #define se second #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int P=786433,g=10; inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;} inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } const int N=2e5+5; struct eg{int v,nx;}e[N<<1];int head[N],tot; inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int ind[P],fpow[P]; inline void init(){ fpow[0]=1; for(R int x=g,i=1;x!=1;x=mul(x,g),++i)ind[x]=i,fpow[i]=x; } inline int calc(R int x,R int y){ if(x%=P,!x)return 0; return fpow[1ll*ind[x]*y%(P-1)]; } typedef pair<int,int> pi; int a[N],n,res; vector<pi> dfs(int u,int fa){ vector<pi> now(1,pi(a[u],1)); go(u)if(v!=fa){ vector<pi> to=dfs(v,u),tt; for(auto &x:to)x.fi&=a[u]; pi p(0,0); for(auto x:to)if(p.fi!=x.fi){ if(p.fi)tt.pb(p); p=x; }else p.se+=x.se; if(p.fi)tt.pb(p); for(const auto &x:now)for(const auto &y:tt) upd(res,1ll*calc(x.fi&y.fi,x.fi&y.fi)*x.se*y.se%P); now.insert(now.end(),tt.begin(),tt.end()); } return now; } int main(){ // freopen("testdata.in","r",stdin); scanf("%d",&n),init(); fp(i,1,n)scanf("%d",&a[i]),upd(res,calc(a[i],a[i])); for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u); dfs(1,0); printf("%d\n",res); return 0; }
先考慮一個暴力,把\(S\)中每個數的倍數都存在一個\(bitset\)裏,記爲\(A\),那麼答案就是\(A\&(A>>1)\&(A>>2)\)
然而這樣顯然會\(T\),那麼咱們考慮設閾值,對於\(x\)大於閾值的部分,咱們仍是直接枚舉倍數並記到\(A\)裏,不然咱們找出\(x\)的倍數的循環節的狀況,而後在循環節上對\(A\)處理就好了
順便記得找循環節的時候千萬別取模……\(\%\)的常數很是大甚至會\(T\)……
//quming #include<bits/stdc++.h> #define R register #define pc(x) __builtin_popcountll(x) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; typedef unsigned long long ll; const int N=(1000000000>>6)+233; struct Bit{ ll p[N]; inline void ins(R int x){p[x>>6]|=(1ull<<(x&63));} }A; ll b[64*64+5];int n,S,mx,res; int main(){ // freopen("testdata.in","r",stdin); scanf("%d%d",&n,&S),mx=(n>>6); for(R int x;S;--S){ scanf("%d",&x); if(x==1)return printf("%d\n",n-2),0; if(x<=64){ fp(i,0,x-1)b[i]=0; for(R int i=0;i<(x<<6);i+=x)b[i>>6]|=(1ull<<(i&63)); for(R int i=0,j=0;i<=mx;++i){ A.p[i]|=b[j]; if(++j==x)j=0; } }else for(R int i=x;i<=n;i+=x)A.ins(i); } A.p[(n+1)>>6]&=(1ull<<((n+1)&63))-1; fp(i,0,mx)res+=pc(A.p[i]&(A.p[i]>>1)&(A.p[i]>>2)); fp(i,1,mx){ R ll tmp=(A.p[i-1]>>62)|((A.p[i]&3)<<2); res+=pc(tmp&(tmp>>1)&(tmp>>2)); } printf("%d\n",res); return 0; }