储能表
/* 引自zyz大佬的数学思想 */ #include<cstdio> #include<iostream> using namespace std; typedef long long ll; #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif ll k;int T,p; int calc(ll x,ll i,ll j){ if(i<j) swap(i,j); x/=i; x*=i; j%=p; ll l=max(0LL,x-k); ll r=max(0LL,x+i-k); ll ans=(l+r-1); if(!(ans&1)){ ans=(ans>>1)%p; ans=(ans*((r-l)%p))%p; } else{ ans=ans%p; ans=(ans*((r-l>>1)%p))%p; } return ans*j%p; } int solve(ll n,ll m){ ll ans=0; for(ll i=1LL<<60,x=0;i;i>>=1){ if(n&i){ for(ll j=1LL<<60,y=0;j;j>>=1){ if(m&j){ ans+=calc(x^y,i,j); ans%=p; y+=j; } } x+=i; } } return ans; } int main(){ for(scanf("%d",&T);T--;){ ll n,m; scanf(LL LL LL LL,&n,&m,&k,&p); printf("%d ",solve(n,m)); } return 0; }
数字配对
/* 二分图-->费用流 */ #include<cstdio> #include<cstdlib> #include<iostream> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif using namespace std; typedef long long i64; const int N=4005; const int M=5e5+5; const i64 inf=10000000000000LL; struct edge{int v,next;i64 cap,cost;}e[M];int tot=1,head[N]; int n,m,S,T,q[N],prev[N];bool vis[N]; i64 a[N],b[N],c[N]; i64 answ,ansf,dis[N]; void add(int x,int y,i64 z,i64 cost){ e[++tot].v=y;e[tot].cap=z;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].cap=0;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot; } bool spfa(){ for(int i=S;i<=T;i++) vis[i]=0,dis[i]=-inf; unsigned short h=0,t=1;q[t]=S;dis[S]=0; while(h!=t){ int x=q[++h];vis[x]=0; for(int i=head[x];i;i=e[i].next){ if(e[i].cap&&dis[e[i].v]<dis[x]+e[i].cost){ dis[e[i].v]=dis[x]+e[i].cost; prev[e[i].v]=i; if(!vis[e[i].v]){ vis[e[i].v]=1; //if(dis[e[i].v]>dis[x]){ // q[h--]=e[i].v; //} //else{ q[++t]=e[i].v; //} } } } } return answ+dis[T]>=0; } void augment(){ i64 flow=inf; if(dis[T]<0) flow=answ/(-dis[T]); for(int i=T;i!=S;i=e[prev[i]^1].v){ flow=min(flow,e[prev[i]].cap); } for(int i=T;i!=S;i=e[prev[i]^1].v){ e[prev[i]].cap-=flow; e[prev[i]^1].cap+=flow; } ansf+=flow; answ+=flow*dis[T]; } i64 fpow(i64 a,i64 p,i64 mod){ i64 res=1; for(;p;p>>=1,a=a*a%mod) if(p&1) res=res*a%mod; return res; } bool judge(i64 x){ if(x<2) return 0; if(x==2) return 1; if(x&1^1) return 0; i64 a,t; for(int i=1;i<=10;i++){ a=rand()%M; if(a>=x&&a%x==0) continue; t=fpow(a,x-1,x); if(t!=1) return 0; } return 1; } int main(){ scanf("%d",&n);S=0,T=n<<1|1; for(int i=1;i<=n;i++) scanf(LL,&a[i]); for(int i=1;i<=n;i++){ scanf(LL,&b[i]); add(S,i,b[i],0); add(i+n,T,b[i],0); } for(int i=1;i<=n;i++) scanf(LL,&c[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j) continue; if(a[j]&&!(a[i]%a[j])&&judge(a[i]/a[j])){ add(i,j+n,inf,c[i]*c[j]); } if(a[i]&&!(a[j]%a[i])&&judge(a[j]/a[i])){ add(i,j+n,inf,c[i]*c[j]); } } } while(spfa()) augment(); printf(LL,ansf/2); return 0; }
游戏
/* 树链剖分+树上差分 */ #include<cstdio> #include<algorithm> using namespace std; #define lc k<<1 #define rc k<<1|1 #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif typedef long long ll; const ll inf=123456789123456789LL; const int N=1e5+5; struct line{ll a,b;}; struct edge{int v,w,next;}e[N<<1];int tot,head[N]; struct sgt{ ll mn; line a; bool tag; sgt(){mn=inf;tag=0;} }tr[N<<2]; int n,m,fa[N],son[N],siz[N],pos[N],top[N],dep[N],q[N]; ll ans,dfn[N],dis[N]; void add(int x,int y,int z){ e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].w=z;e[tot].next=head[y];head[y]=tot; } void bfs(){ int h=0,t=1;q[t]=1;dep[1]=1;fa[1]=1; while(h!=t){ int x=q[++h]; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(v!=fa[x]){ fa[v]=x; dep[v]=dep[x]+1; dis[v]=dis[x]+e[i].w; q[++t]=v; } } } for(int j=n;j;j--){ int x=q[j];siz[x]=1;son[x]=0; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(fa[v]==x){ siz[x]+=siz[v]; if(siz[son[x]]<siz[v]) son[x]=v; } } } int bfs_cnt=0; for(int j=1;j<=n;j++){ int x=q[j]; if(!pos[x]){ for(int y=x;y;y=son[y]){ pos[y]=++bfs_cnt; dfn[bfs_cnt]=dis[y]; top[y]=x; } } } } int lca(int x,int y){ for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); } return dep[x]<dep[y]?x:y; } ll get(line a,ll x){ return a.a*x+a.b; } void change(int k,int l,int r,int opl,int opr,line a){ int mid=l+r>>1; if(opl<=l&&r<=opr){ tr[k].mn=min(tr[k].mn,min(get(a,dfn[l]),get(a,dfn[r]))); if(!tr[k].tag){ tr[k].tag=1;tr[k].a=a; return ; } if(l==r){ if(get(a,dfn[l])<get(tr[k].a,dfn[l]))tr[k].a=a; return ; } bool b0=get(a,dfn[l])<get(tr[k].a,dfn[l]); bool b1=get(a,dfn[mid])<get(tr[k].a,dfn[mid]); bool b2=get(a,dfn[r])<get(tr[k].a,dfn[r]); if(!b0&&!b2) return ; if(b0&&b2){ tr[k].a=a; return ; } if(b1){ swap(a,tr[k].a); b0^=1;b2^=1; } if(b0) change(lc,l,mid,opl,opr,a); if(b2) change(rc,mid+1,r,opl,opr,a); return ; } if(opl<=mid) change(lc,l,mid,opl,opr,a); if(mid+1<=opr) change(rc,mid+1,r,opl,opr,a); tr[k].mn=min(tr[k].mn,min(tr[lc].mn,tr[rc].mn)); } void query(int k,int l,int r,int opl,int opr){ if(opl<=l&&r<=opr){ ans=min(ans,tr[k].mn); return ; } if(tr[k].tag){ ans=min(ans,min(get(tr[k].a,dfn[max(l,opl)]),get(tr[k].a,dfn[min(r,opr)]))); } int mid=l+r>>1; if(opl<=mid) query(lc,l,mid,opl,opr); if(mid+1<=opr) query(rc,mid+1,r,opl,opr); } int main(){ scanf("%d%d",&n,&m); for(int i=1,x,y,z;i<n;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); } bfs(); for(int i=1,opt,x,y,z;i<=m;i++){ scanf("%d",&opt); if(opt&1){ ll a,b; scanf("%d%d",&x,&y); scanf(LL LL ,&a,&b); z=lca(x,y); ll Ax=-a,Bx=a*dis[x]+b; ll Ay=a,By=a*(-2*dis[z]+dis[x])+b; for(;dep[top[x]]>dep[z];x=fa[top[x]]){ change(1,1,n,pos[top[x]],pos[x],(line){Ax,Bx}); } for(;dep[top[y]]>dep[z];y=fa[top[y]]){ change(1,1,n,pos[top[y]],pos[y],(line){Ay,By}); } if(x!=z) change(1,1,n,pos[z],pos[x],(line){Ax,Bx}); else if(y!=z) change(1,1,n,pos[z],pos[y],(line){Ay,By}); else change(1,1,n,pos[z],pos[z],(line){Ax,Bx}); } else{ scanf("%d%d",&x,&y); ans=inf; z=lca(x,y); for(;dep[top[x]]>dep[z];x=fa[top[x]]){ query(1,1,n,pos[top[x]],pos[x]); } for(;dep[top[y]]>dep[z];y=fa[top[y]]){ query(1,1,n,pos[top[y]],pos[y]); } if(x!=z) query(1,1,n,pos[z],pos[x]); else if(y!=z) query(1,1,n,pos[z],pos[y]); else query(1,1,n,pos[z],pos[z]); printf(LL " ",ans); } } return 0; }