暴力枚举每一个点,删除改点后生成树计数,但1e8为什么不超时。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int mod=1000000007; LL pow_mod(LL a,LL n){ LL t=a,res=1; while(n){ if(n&1) res=(res*t)%mod; t=(t*t)%mod; n/=2; } return res; } LL inv(LL a,LL m){ return pow_mod(a,m-2); } struct Matrix{ int mat[105][105]; void init(){ memset(mat,0,sizeof(mat)); } int det(int n){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) mat[i][j]=(mat[i][j]%mod+mod)%mod; int res=1; for(int i=0;i<n;i++){ for(int j=i;j<n;j++) if(mat[j][i]!=0){ for(int k=i;k<n;k++) swap(mat[i][k],mat[j][k]); if(i!=j) res=(-res+mod)%mod; break; } if(mat[i][i]==0){ res=-1; break; } for(int j=i+1;j<n;j++){ int mut=((LL)mat[j][i]*inv(mat[i][i],mod))%mod; for(int k=i;k<n;k++) mat[j][k]=(mat[j][k]-((LL)mat[i][k]*mut)%mod+mod)%mod; } res=((LL)res*mat[i][i])%mod; } return res; } }; Matrix ret; int g[105][105]; int in[105]; int t,n,m; void pre(int x){ ret.init(); for(int i=0;i<n;i++){ if(i==x) continue; int ii=i; if(i>x&&x!=-1) ii--; for(int j=0;j<n;j++){ if(i==j||j==x) continue; int jj=j; if(j>x&&x!=-1) jj--; if(g[i][j]){ ret.mat[ii][jj]=-1; ret.mat[ii][ii]++; } } } } int main(){ scanf("%d",&t); while(t--){ memset(g,0,sizeof(g)); memset(in,0,sizeof(in)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); g[u-1][v-1]=1; g[v-1][u-1]=1; in[u-1]++; in[v-1]++; } pre(-1); int temp=ret.det(n-1); if(temp<0) temp++; int ans=(LL)temp*(n*(n+1)/2)%mod; for(int i=0;i<n;i++){ pre(i); int temp=ret.det(n-2); if(temp<0) temp++; ans-=(LL)(in[i]*(i+1)%mod)*temp%mod; if(ans<0) ans+=mod; } printf("%d ",ans); } return 0; }
最大流,直接不行,反过来求最小割。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #define inf 0x3f3f3f3f using namespace std; typedef long long LL; LL n,c; LL p[100005]; LL s[100005]; LL w[100005]; int main(){ scanf("%lld%lld",&n,&c); for(LL i=1;i<=n;i++) scanf("%lld",&p[i]); for(LL i=1;i<=n;i++) scanf("%lld",&s[i]); LL sum=0,ans=1e18; for(LL i=1;i<=n;i++){ w[i]=p[i]-s[i]+(i-1)*c; sum+=s[i]; } sort(w+1,w+1+n); for(LL i=1;i<=n;i++){ sum+=w[i]-(i-1)*c; ans=min(ans,sum); } printf("%lld ",ans); return 0; }
二分答案,尺取判断。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const double eps=1e-8; const int N=100005; int n,m,k; int a[N],b[N]; bool check(double mid){ //cout<<"mid="<<mid<<endl; int num=0; int L=1,R=1; while(1){ if(R>n) break; double temp=(1.0*a[L])/b[R]; //cout<<L<<" "<<R<<" "; //cout<<temp<<endl; if(mid-temp>eps&&L<n) L++; else if(mid-temp>eps&&L==n) R++; else{ num+=n-L+1; //cout<<"num="<<num<<endl; R++; } //cout<<endl; } //cout<<"num="<<num<<endl; //system("pause"); if(num>=k) return true; else return false; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); for(int i=1;i<=m;i++) scanf("%d",&b[i]); sort(b+1,b+1+m); double l=0,r=1.0*a[n]/b[1]; while(abs(r-l)>eps){ double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } printf("%.2lf ",l); } return 0; }
矩阵快速幂。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const LL s1=1e9+7; struct Mat{ LL a[5][5]; void init(){ a[0][0]=5;a[0][1]=3;a[0][2]=0;a[0][3]=0;a[0][4]=1; a[1][0]=3;a[1][1]=2;a[1][2]=0;a[1][3]=0;a[1][4]=1; a[2][0]=2;a[2][1]=1;a[2][2]=0;a[2][3]=0;a[2][4]=1; a[3][0]=1;a[3][1]=1;a[3][2]=0;a[3][3]=0;a[3][4]=0; a[4][0]=0;a[4][1]=0;a[4][2]=0;a[4][3]=0;a[4][4]=1; } }; Mat operator *(Mat a,Mat b){ Mat c; for(LL i=0;i<5;i++) for(LL j=0;j<5;j++){ c.a[i][j]=0; for(LL k=0;k<5;k++) c.a[i][j]+=a.a[i][k]*b.a[k][j]; c.a[i][j]%=s1; } return c; } Mat operator ^(Mat p,LL k){ Mat ans; ans.init(); while(k){ if(k&1) ans=ans*p; k/=2; p=p*p; } return ans; } int main(){ LL f1,f2,f3,f4,n; while(cin>>f1>>f2>>n){ f3=f1+f2; f4=f2+f3-1; Mat x; memset(x.a,0,sizeof(x.a)); x.a[0][0]=f4%s1; x.a[1][0]=f3%s1; x.a[2][0]=f2%s1; x.a[3][0]=f1%s1; x.a[4][0]=1; Mat a; a.init(); Mat ans=x; if(n>4) ans=(a^((n-1)/4-1))*x; for(int i=0;i<5;i++){ for(int j=0;j<5;j++){ //cout<<ans.a[i][j]<<" "; } //cout<<endl; } cout<<ans.a[3-(n-1)%4][0]%s1<<endl; } return 0; }
线段树或者ST表统计区间最大,最小,gcd以及是否有相同的数字。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <map> #define lson (id*2) #define rson (id*2+1) #define mid ((l+r)/2) using namespace std; const int N=1e5+5; int gcd(int x,int y){ return y==0?x:gcd(y,x%y); } struct node{ int mi,ma,p; } tre[N*5]; void push_up(int id){ tre[id].ma=max(tre[lson].ma,tre[rson].ma); tre[id].mi=min(tre[lson].mi,tre[rson].mi); tre[id].p=max(tre[lson].p,tre[rson].p); } void build(int id,int l,int r){ if(l==r){ tre[id].ma=0; tre[id].mi=0; tre[id].p=0; return; } build(lson,l,mid); build(rson,mid+1,r); push_up(id); return; } void add(int id,int l,int r,int pos,int tt){ if(l==r){ tre[id].ma=tt; tre[id].mi=tt; return; } if(pos<=mid) add(lson,l,mid,pos,tt); else add(rson,mid+1,r,pos,tt); push_up(id); return; } void add_pos(int id,int l,int r,int pos,int tt){ if(l==r){ tre[id].p=tt; return; } if(pos<=mid) add_pos(lson,l,mid,pos,tt); else add_pos(rson,mid+1,r,pos,tt); push_up(id); return; } int query_max(int id,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return tre[id].ma; } int ans=0; if(ql<=mid) ans=max(ans,query_max(lson,l,mid,ql,qr)); if(qr>mid) ans=max(ans,query_max(rson,mid+1,r,ql,qr)); return ans; } int query_min(int id,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return tre[id].mi; } int ans=1e9+7; if(ql<=mid) ans=min(ans,query_min(lson,l,mid,ql,qr)); if(qr>mid) ans=min(ans,query_min(rson,mid+1,r,ql,qr)); return ans; } int query_num(int id,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return tre[id].p; } int ans=0; if(ql<=mid) ans=max(ans,query_num(lson,l,mid,ql,qr)); if(qr>mid) ans=max(ans,query_num(rson,mid+1,r,ql,qr)); return ans; } int tre_gcd[N*5]; void push_up_gcd(int id){ tre_gcd[id]=gcd(tre_gcd[lson],tre_gcd[rson]); return; } void build_gcd(int id,int l,int r){ if(l==r){ tre_gcd[id]=0; return; } build_gcd(lson,l,mid); build_gcd(rson,mid+1,r); push_up_gcd(id); return; } void add_gcd(int id,int l,int r,int pos,int tt){ if(l==r){ tre_gcd[id]=tt; return; } if(pos<=mid) add_gcd(lson,l,mid,pos,tt); else add_gcd(rson,mid+1,r,pos,tt); push_up_gcd(id); return; } int query_gcd(int id,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ return tre_gcd[id]; } int ans=-1; if(ql<=mid) ans=query_gcd(lson,l,mid,ql,qr); if(qr>mid){ if(ans!=-1) ans=gcd(ans,query_gcd(rson,mid+1,r,ql,qr)); else ans=query_gcd(rson,mid+1,r,ql,qr); } return ans; } int x[N]; int pos[N*10]; int main(){ int n,q; while(scanf("%d%d",&n,&q)!=EOF){ build(1,1,n); build_gcd(1,1,n); memset(pos,0,sizeof(pos)); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); add(1,1,n,i,x[i]); add_pos(1,1,n,i,pos[x[i]]); pos[x[i]]=i; } for(int i=1;i<n;i++){ add_gcd(1,1,n-1,i,abs(x[i+1]-x[i])); } for(int i=1;i<=q;i++){ int L,R; scanf("%d%d",&L,&R); int x1=query_max(1,1,n,L,R); int x2=query_min(1,1,n,L,R); int ok=query_num(1,1,n,L,R); //cout<<ok<<endl; if(x1==x2||(R-L)<=1){ printf("Yes "); } else{ if(ok<L){ int x3=query_gcd(1,1,n-1,L,R-1); if((x1-x2)==x3*(R-L)) printf("Yes "); else printf("No "); } else printf("No "); } } } return 0; }