使用\(Prim\)算法求最小生成树,复杂度\(O(n^2)\)
#include<bits/stdc++.h> #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 2500100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-b+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } int n,x[5050],y[5050],frm[5050];ll low[5050],e[5050][5050]; inline ll sqr(ll x){return x*x;} inline ll dis(int i,int j){return sqr(x[i]-x[j])+sqr(y[i]-y[j]);} const ll inf=9e18; ll prim() { rep(i,1,n) low[i]=e[1][i],frm[i]=1; frm[1]=-1;ll mx=0,mn;int v; rep(i,2,n) { v=-1;mn=inf; rep(j,1,n) if(~frm[j]&&low[j]<mn) v=j,mn=low[j]; if(v==-1) continue; frm[v]=-1,mx=max(low[v],mx); rep(j,1,n) if(~frm[j]&&low[j]>e[v][j]) low[j]=e[v][j],frm[j]=v; } return mx; } int main() { rep(T,1,read()) { scanf("%d",&n); rep(i,1,n) x[i]=read(),y[i]=read(); rep(i,1,n) rep(j,i,n) if(i==j) e[i][j]=0; else e[i][j]=e[j][i]=dis(i,j); printf("%lld\n",prim()); } }
两个修改操作分别相当于减少二进制上最小的\(1\)以及把最高位的\(1\)左移一位
因为\(1\)的数量不会改变,因此最多减小\(31\)次后数就会变成\(0\)
可以把最高位的\(1\)用线段树维护,相当于支持区间乘二,区间和查询以及单点置零
对于其余位的\(1\)暴力维护,用树状数组单点修改,区间查询;再用并查集+链表维护已经被置零的数
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 100100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-(b))%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } inline void inc(int &x,int y){x=pls(x,y);} inline void tms(int &x,int y){x=mul(x,y);} int n,g[MAXN],h[MAXN],fa[MAXN],sum[MAXN<<2],tag[MAXN<<2],isz[MAXN<<2],c[MAXN]; void add(int x,int w){for(;x<=n;x+=x&-x) inc(c[x],w);} int pres(int x,int res=0){for(;x;x-=x&-x) inc(res,c[x]);return res;} int gets(int l,int r){return mns(pres(r),pres(l-1));} int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} inline void upd(int k) { sum[k]=pls(sum[k<<1],sum[k<<1|1]); isz[k]=isz[k<<1]&isz[k<<1|1]; } inline void pshd(int k) { tms(sum[k<<1],tag[k]);tms(sum[k<<1|1],tag[k]); tms(tag[k<<1],tag[k]);tms(tag[k<<1|1],tag[k]); tag[k]=1; } void build(int k,int l,int r) { tag[k]=1;if(l==r) {sum[k]=g[l],isz[k]=0;return ;}int mid=l+r>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r);upd(k); } void mdf(int k,int l,int r,int a,int b) { if(isz[k]) return ;if(a<=l&&r<=b) {tms(sum[k],2);tms(tag[k],2);return ;} int mid=l+r>>1;if(tag[k]!=1) pshd(k); if(a<=mid) mdf(k<<1,l,mid,a,b); if(b>mid) mdf(k<<1|1,mid+1,r,a,b); upd(k); } void dec(int k,int l,int r,int x) { if(l==r) {isz[k]=1,sum[k]=0;return ;} int mid=l+r>>1;if(tag[k]!=1) pshd(k); x<=mid?dec(k<<1,l,mid,x):dec(k<<1|1,mid+1,r,x); upd(k); } int query(int k,int l,int r,int a,int b) { if(isz[k]) return 0;if(a<=l&&r<=b) return sum[k]; int mid=l+r>>1,res=0;if(tag[k]!=1) pshd(k); if(a<=mid) res=query(k<<1,l,mid,a,b); if(b>mid) inc(res,query(k<<1|1,mid+1,r,a,b));return res; } void work(int l,int r) { for(int tmp;l<=r;l++) { l=find(l);if(l>r) break; if(h[l]>0) {tmp=h[l]&-h[l];add(l,-tmp);h[l]-=tmp;} else if(!h[l]) {dec(1,1,n,l);h[l]=-1,fa[l]=l+1;} } } int main() { int t,a,b,x; rep(T,1,read()) { n=read();rep(i,1,n) { scanf("%d",&g[i]);fa[i]=i; for(x=g[i];x!=(x&-x);x-=x&-x); h[i]=g[i]-x;add(i,g[i]-x);g[i]=x; } build(1,1,n);fa[n+1]=n+1; rep(Q,1,read()) { scanf("%d%d%d",&t,&a,&b); if(t==1) printf("%d\n",pls(pls(gets(a,b),query(1,1,n,a,b)),MOD)); else if(t==2) work(a,b); else mdf(1,1,n,a,b); } rep(i,1,n) if(h[i]>0) add(i,-h[i]); } }
E
考虑每一位的贡献,题目相当于在\(n-1\)个空位里插\(\le k-1\)个板,枚举这一位之后的板插在哪里或不插,答案为:
\[\begin{aligned} ans&=\sum\limits_{x=0}^k\sum\limits_{i=1}^na_i\lgroup \sum\limits_{j=0}^{n-i-1}10^j\binom{n-2-j}{x-1}+10^{n-i}\binom{i-1}{x}\rgroup\\ &=\sum\limits_{i=1}^na_i\lgroup\sum\limits_{j=0}^{n-i-1}10^j\sum\limits_{x=0}^{k-1}\binom{n-2-j}{x}+10^{n-i}\sum\limits_{x=0}^k\binom{i-1}{x}\rgroup \end{aligned} \]注意到两个组合数求和都是对每一行求一段连续固定长度的和,则可以算出第一行后直接递推
处理出\(sum_i=\sum\limits_{j=0}^{k-1}\binom{i}{j}\)后,前半部分即为\(\sum\limits_{j=0}^{n-i-1}10^jsum_{n-2-j}\),也很容易递推
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 1001001 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-(b)+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } int k,n,m,fac[MAXN],ifac[MAXN],ans,pw10[MAXN]; int f[MAXN],g[MAXN],s[MAXN];char ch[MAXN]; int q_pow(int bas,int t,int res=1) { for(;t;t>>=1,bas=mul(bas,bas)) if(t&1) res=mul(res,bas);return res; } #define inv(x) q_pow(x,MOD-2) inline int C(int n,int m) { if(m<0||n<m) return 0; return mul(fac[n],mul(ifac[m],ifac[n-m])); } void mem(int n=1e6) { fac[0]=ifac[0]=pw10[0]=1; rep(i,1,n) fac[i]=mul(fac[i-1],i),pw10[i]=mul(pw10[i-1],10); ifac[n]=inv(fac[n]); dwn(i,n-1,1) ifac[i]=mul(ifac[i+1],i+1); } ll Force(ll ans=0,ll res=0) { rep(x,0,k) rep(i,1,n) { res=0; rep(j,0,n-i-1) res=pls(res,mul(C(n-2-j,x-1),pw10[j])); res=pls(res,mul(pw10[n-i],C(i-1,x))); res=mul(res,g[i]),ans=pls(ans,res); } return ans; } int main() { int res,tmp;mem(); rep(T,1,read()) { k=read()-1;scanf("%s",ch+1);n=strlen(ch+1); rep(i,1,n) g[i]=ch[i]-'0';ans=0;tmp=1; //cout<<Force()<<endl; rep(i,1,n) res=mul(tmp,mul(g[i],pw10[n-i])),ans=pls(ans,res), tmp=mul(tmp,2),tmp=mns(tmp,C(i-1,k)); if(!k) {printf("%d\n",ans);continue;} f[0]=tmp=1;rep(i,1,n) tmp=mul(tmp,2),tmp=mns(tmp,C(i-1,k-1)),f[i]=tmp; rep(i,0,n-2) s[i]=mul(pw10[i],f[n-2-i]); rep(i,1,n-2) s[i]=pls(s[i],s[i-1]); rep(i,1,n) ans=pls(ans,mul(g[i],s[n-i-1])); printf("%d\n",ans); } }
对于每个数,每次操作相当于除一些质因数
令\(f[i]\)表示\(i\)这个数质数分解后的质数幂次之和,则原题相当于对一些石子数量为\(f[a_i]\)的石子做\(nim\)博弈
线性筛预处理\(f_i\)
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 10010010 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-(b)+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } int ntp[MAXN],f[MAXN],p[MAXN/7],tot,n,ans; void mem(int n=1e7) { rep(i,2,n) { if(!ntp[i]) p[++tot]=i,f[i]=1; rep(j,1,tot) if(i*p[j]>n) break; else {ntp[i*p[j]]=1,f[i*p[j]]=f[i]+1;if(i%p[j]==0) break;} } } int main() { mem();rep(T,1,read()) { n=read();rep(i,1,n) ans^=f[read()]; puts(ans?"Alice":"Bob");ans=0; } }
对于一个正方形和圆来说,正方形能够被圆完全包含的中心位置也形成一个圆
题目转化为两个圆面积求交
特判一下圆\(B\)无法包含正方形以及两个圆包含相离的情况
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 100100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-(b)+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const db pi=acos(-1); db r1,r2,d,len; struct Point{db x,y;}a,b; inline db sqr(db x){return x*x;} inline db dis(Point a,Point b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} db solve() { db d=dis(a,b); if(d>=r1+r2) return 0.0; if(d<=r1-r2) return pi*r2*r2; if(d<=r2-r1) return pi*r1*r1; db p=(r1+r2+d)/2.0; db a1=acos((r1*r1+d*d-r2*r2)/(2.0*r1*d)); db a2=acos((r2*r2+d*d-r1*r1)/(2.0*r2*d)); return a1*r1*r1+a2*r2*r2-2.0*sqrt(p*(p-r1)*(p-r2)*(p-d)); } int main() { rep(T,1,read()) { cin>>r1>>a.x>>a.y>>r2>>b.x>>b.y>>len; if(len*len>=r2*r2*2) {puts("0.000000");continue;} r1=sqrt(sqr(r1)-sqr(len/2))-len/2; r2=sqrt(sqr(r2)-sqr(len/2))-len/2; printf("%.6lf\n",solve()/(pi*r1*r1)); } }
因为模式串的长度不超过\(30\),可以用字符串哈希暴力算出母串所有长度不超过\(30\)的子串的答案
每次\(check\)所有模式串即可
#include<bits/stdc++.h> #define inf 2139062143 #define ll long long #define db double #define ld long double #define ull unsigned long long #define MAXN 400100 #define MOD 998244353 #define Fill(a,x) memset(a,x,sizeof(a)) #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) #define ren for(int i=fst[x];i;i=nxt[i]) #define pls(a,b) (a+b)%MOD #define mns(a,b) (a-(b)+MOD)%MOD #define mul(a,b) (1LL*(a)*(b))%MOD #define pii pair<int,int> #define Clear(x) {x.clear();vector<pii> (x).swap(x);} #define fi first #define se second #define pb push_back using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int mod=998244353,bas=137; int n,m,len,p[MAXN],res[MAXN],ans[MAXN]; char ch[MAXN],cc[40]; int w1[MAXN],w2[MAXN],val[MAXN]; vector<pii> vec[40];map<int,int> mp; int hsh[MAXN],pw[MAXN]; inline int calc(int l,int r) { return (hsh[r]-(1LL*hsh[l-1]*pw[r-l+1])%mod+mod)%mod; } void work(int x) { int tmp,tot=0; rep(i,1,m-x+1) { tmp=calc(i,i+x-1),w1[i]=tmp; if(!mp[w1[i]]) mp[w1[i]]=++tot,w2[i]=tot; else w2[i]=mp[w1[i]]; } rep(i,1,tot) p[i]=-m,res[i]=0; rep(i,1,m-x+1) if(p[w2[i]]<=i-x) res[w2[i]]++,p[w2[i]]=i; for(auto t:vec[x]) { tmp=t.se; if(!mp.count(tmp)) ans[t.fi]=0; else ans[t.fi]=res[mp[tmp]]; } Clear(vec[x]);mp.clear(); } int main() { int h1;rep(T,1,read()) { scanf("%s",ch+1);m=strlen(ch+1);pw[0]=1; rep(i,1,m) pw[i]=(1LL*pw[i-1]*bas)%mod,hsh[i]=((1LL*hsh[i-1]*bas)%mod+ch[i]-'a'+1)%mod; n=read();rep(i,1,n) { scanf("%s",cc+1);len=strlen(cc+1);h1=0; rep(i,1,len) h1=((1LL*h1*bas)%mod+cc[i]-'a'+1)%mod; vec[len].pb({i,h1}); } rep(i,1,30) if(vec[i].size()) work(i); rep(i,1,n) printf("%d\n",ans[i]); } }