傳送門html
菜爆了……總共只有一道題會作的……並且也沒有短裙好難過c++
爲啥必須得有手機才能註冊帳號啊喂……歧視麼……spa
推一下柿子大概就是code
\[x-\sqrt{n}=y+z+2\sqrt{yz}\]htm
若是\(\sqrt{n}\)是無理數,那麼就是blog
\[x=y+z,{n\over 4}=yz\]排序
那麼要知足\(n\)必須是\(4\)的倍數,而後爆搜\({n\over 4}\)的因子,統計答案就好了get
若是\(n\)不是無理數,那麼it
\[x=\sqrt{n}+(y-z)^2\]class
這東西一看就是無限解吧……
//minamoto #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) 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; } const int N=1e5+5; int p[N],vis[N],m; void init(int n=1e5){ fp(i,2,n){ if(!vis[i])p[++m]=i; for(R int j=1;j<=m&&1ll*i*p[j]<=n;++j){ vis[i*p[j]]=1; if(i%p[j]==0)break; } } } const int P=1e9+7; int st[N],c[N],top,res,sum,n,sqr; void dfs(int x,int s){ if(x==top+1){ if(n/4/s>s)return; res=(res+1)%P,sum=(sum+s+n/4/s)%P; return; } for(R int i=0,t=1;i<=c[x];++i,t*=st[x]) dfs(x+1,s*t); } void solve(int x){ top=0; for(R int i=1;1ll*p[i]*p[i]<=x;++i)if(x%p[i]==0){ st[++top]=p[i],c[top]=0; while(x%p[i]==0)x/=p[i],++c[top]; } if(x>1)st[++top]=x,c[top]=1; res=sum=0; dfs(1,1); } int main(){ // freopen("testdata.in","r",stdin); init(); int T=read(); while(T--){ n=read(),sqr=sqrt(n); if(n==0||sqr*sqr==n){puts("infty");continue;} if(n%4){puts("0 0");continue;} solve(n/4); printf("%d %d\n",res,1ll*sum*n/4%P); } return 0; }
這麼傻逼的一個\(dp\)我竟然沒想出來……
若是沒有遍歷完全部\(n\)個城市,那麼遍歷到的城市顯然是一條鏈。咱們能夠設\(f_{i,j,k}\)表示在第\(i\)天,左邊有\(j\)個已經訪問過的城市,右邊有\(k\)個已經訪問過的城市的機率。轉移顯然
若是遍歷完了全部的\(n\)個城市咋辦?發現其實不當作環也沒問題,直接把訪問城市個數對\(n\)取\(\min\)就能夠了
//minamoto #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) 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; } const int N=505,P=1e9+7; inline void Add(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; } int f[N][N][N],g[N],T,n,m,k,p,q,res; int main(){ // freopen("testdata.in","r",stdin); T=read(); while(T--){ n=read(),m=read(),k=read(),p=read(),q=read(),res=0; fp(i,1,m)fp(j,0,i-1)fp(k,0,i-1)f[i][j][k]=0; fp(i,1,n)g[i]=0; f[1][0][0]=1; fp(i,1,m-1)fp(j,0,i-1)fp(k,0,i-1) Add(f[i+1][max(j-1,0)][k+1],mul(f[i][j][k],p)), Add(f[i+1][j+1][max(k-1,0)],mul(f[i][j][k],q)), Add(f[i+1][j][k],mul(f[i][j][k],100-p-q)); fp(i,0,m-1)fp(j,0,m-1)Add(g[min(i+j+1,n)],f[m][i][j]); fp(i,1,n)Add(res,mul(g[i],ksm(i,k))); printf("%d\n",res); } return 0; }
若是一個點對知足條件,說明它們之間存在至少兩條邊不重複的路徑,也就是說明它們在同一個邊雙裏
動態維護邊雙,看這裏
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #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) 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; } const int N=1e6+5,M=2e6+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;} struct EG{int u,v,is;}st[M]; int fa[N],ga[N],sz[N],dep[N],q[N]; int n,m;ll res,sum; int find(int x){return ga[x]==x?x:ga[x]=find(ga[x]);} inline ll calc(R int x){return 1ll*x*(x-1)>>1;} void bfs(int u){ int h=1,t=0;q[++t]=u,dep[u]=1; while(h<=t){ u=q[h++]; go(u)if(v!=fa[u])q[++t]=v,dep[v]=dep[u]+1,fa[v]=u; } } void merge(int u,int v){ u=find(u),v=find(v); while(u!=v){ if(dep[u]<dep[v])swap(u,v); res-=calc(sz[find(fa[u])]),res-=calc(sz[u]), sz[ga[fa[u]]]+=sz[u],res+=calc(sz[ga[fa[u]]]); u=ga[u]=ga[fa[u]]; } } int main(){ // freopen("testdata.in","r",stdin); int T=read(); while(T--){ n=read(),m=read(),tot=0,sum=res=0; fp(i,1,n)ga[i]=i,sz[i]=1,head[i]=0,dep[i]=0; for(R int i=1,u,v,x,y;i<=m;++i){ x=read(),y=read(),u=find(x),v=find(y),st[i].u=x,st[i].v=y; if(u!=v){ add(x,y),add(y,x),st[i].is=1; sz[u]>sz[v]?ga[v]=u:sz[u]<sz[v]?ga[u]=v:(ga[v]=u,++sz[u]); }else st[i].is=0; } fp(i,1,n)if(!dep[i])bfs(i); fp(i,1,n)ga[i]=i,sz[i]=1; fp(i,1,m){ if(!st[i].is)merge(st[i].u,st[i].v); sum^=1ll*i*res; // printf("%d %lld\n",i,res); } printf("%lld\n",sum); } return 0; }
咱們設\(f_{i,j,k}\)表示已經完成了\(i\)這個集合的任務,\(A\)結束的時間爲\(j\),\(B\)結束的時間爲\(k\),\(C\)能結束的最先時間是多少。轉移的話大概比較顯然
雖然看着這東西的複雜度彷佛是\(O(T\times 2^6\times 180^2\times 6\times 7)\)……有點炸的樣子……不過由於合法的狀態不是不少,因此咱們只轉移合法的就能夠過了
//minamoto #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 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; } const int N=(1<<6)+5; int sz[N],a[9][9],f[N][205][205],lim; int main(){ // freopen("testdata.in","r",stdin); int T=read();lim=(1<<6); fp(i,1,lim-1)sz[i]=sz[i>>1]+(i&1); while(T--){ fp(i,0,5)fp(j,0,6)a[i][j]=read(); memset(f,0x3f,sizeof(f));f[0][0][0]=0; fp(i,0,lim-1)fp(j,0,180)fp(k,0,180) if(f[i][j][k]<=180) fp(x,0,5)if(i>>x&1^1){ int s=i|(1<<x); cmin(f[s][min(j+a[x][0],181)][k],f[i][j][k]), cmin(f[s][j][min(k+a[x][1],181)],f[i][j][k]), cmin(f[s][j][k],f[i][j][k]+a[x][2]); int t=min(max(f[i][j][k],max(j,k))+a[x][6],181); cmin(f[s][t][t],t); t=min(max(j,k)+a[x][3],181),cmin(f[s][t][t],f[i][j][k]); t=min(max(j,f[i][j][k])+a[x][4],181),cmin(f[s][t][k],t); t=min(max(k,f[i][j][k])+a[x][5],181),cmin(f[s][j][t],t); } int res=0,cnt=0; fp(i,1,lim-1)fp(j,0,180)fp(k,0,180) if(f[i][j][k]<=180&&(sz[i]>res||sz[i]==res&&max(max(j,k),f[i][j][k])<cnt)) res=sz[i],cnt=max(max(j,k),f[i][j][k]); printf("%d %d\n",res,cnt); } return 0; }
orz Gloid
爲了最大化\(LIS\),修改以後\(LIS\)要麼不變要麼\(+1\),一下設原數列的\(LIS\)長度爲\(m\)
那麼咱們先把求\(LIS\)時須要的單調棧給預處理出來,而後分狀況討論
1.\(i\)修改以後\(LIS\)長度\(+1\),那麼咱們須要它前面有一個\(a_j\)知足以\(j\)結尾的\(LIS\)長度爲\(d\),後面有一個\(a_k\)知足以\(k\)開頭的\(LIS\)長度爲\(m-d\),且有\(a_k>a_j+1\),那麼爲了知足修改後的元素最小,咱們顯然是取把它改爲\(a_j+1\)最優
2.若是\(i\)沒辦法在一個長度爲\(m+1\)的數列裏,那麼改完以後\(LIS\)的長度仍是爲\(m-1\)。這個也要分狀況討論。咱們先假設若是有一個\(LIS\)不包含\(i\),那麼顯然它能夠取\(0\)
3.若是全部的\(LIS\)都包含\(i\),那麼它只能取知足存在\(a_j\)長度爲\(d\)和\(a_k\)長度爲\(m-d-1\)的\(a_j+1\)或者\(a_j\)長度爲\(d-1\)且\(a_k\)長度爲\(m-d\)的\(a_j+1\)了
//minamoto #include<bits/stdc++.h> #define R register #define inf 0x3f3f3f3f #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;} 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 K=-1,Z=0; inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} void print(R int x){ if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++K]=z[Z],--Z);sr[++K]='\n'; } const int N=1e5+5; int p[N],q[N],len[N],las[N],now[N],a[N],cnt,T,n,ans,mx; multiset<int>b,c; int main(){ // freopen("testdata.in","r",stdin); T=read(); while(T--){ n=read(); fp(i,1,n)a[i]=read(); q[0]=inf;fp(i,1,n)q[i]=-1; ans=0; fd(i,n,1){ int l=0,r=ans; while(l<=r){ int mid=(l+r)>>1; q[mid]>a[i]?(len[i]=mid+1,l=mid+1):r=mid-1; } las[i]=q[len[i]],q[len[i]]=a[i],cmax(ans,len[i]); } cnt=0,b.clear(),c.clear(); p[0]=-1;fp(i,1,n)p[i]=inf; if(q[ans]>p[0])++cnt; if(q[ans]>p[0]+1)b.insert(p[0]); if(q[ans-1]>p[0]+1)c.insert(p[0]); mx=0; fp(i,1,n){ if(q[len[i]]>p[ans-len[i]]+1)b.erase(b.find(p[ans-len[i]])); if(ans>=len[i]+1&&q[len[i]]>p[ans-len[i]-1]+1)c.erase(c.find(p[ans-len[i]-1])); if(q[len[i]]>p[ans-len[i]])--cnt; q[len[i]]=las[i]; if(q[len[i]]>p[ans-len[i]]+1)b.insert(p[ans-len[i]]); if(ans>=len[i]+1&&q[len[i]]>p[ans-len[i]-1]+1)c.insert(p[ans-len[i]-1]); if(q[len[i]]>p[ans-len[i]])++cnt; if(!b.empty())print(ans+1),sr[K]=' ',print((*b.begin())+1); else if(cnt)print(ans),sr[K]=' ',sr[++K]='0',sr[++K]='\n'; else print(ans),sr[K]=' ',print((*c.begin())+1); int l=0,r=mx; while(l<=r){ int mid=(l+r)>>1; p[mid]<a[i]?(now[i]=mid+1,l=mid+1):r=mid-1; } cmax(mx,now[i]); if(q[ans-now[i]]>p[now[i]]+1)b.erase(b.find(p[now[i]])); if(ans>=now[i]+1&&q[ans-now[i]-1]>p[now[i]]+1)c.erase(c.find(p[now[i]])); if(q[ans-now[i]]>p[now[i]])--cnt; p[now[i]]=a[i]; if(q[ans-now[i]]>p[now[i]]+1)b.insert(p[now[i]]); if(ans>=now[i]+1&&q[ans-now[i]-1]>p[now[i]]+1)c.insert(p[now[i]]); if(q[ans-now[i]]>p[now[i]])++cnt; } } return Ot(),0; }
計蒜幾盒的精度是真的難受啊……
首先,若是咱們能算出\(g[s]\)表示\(s\)這個集合的木棒能組成的最大面積,那麼咱們就能夠直接\(3^n\)的\(dp\)求得答案
因此怎麼算最大面積呢……
首先咱們把\(s\)這個集合裏的木棒按升序排序,記爲\(a_1,a_2,...,a_m\),根據三角形不等式,它們能構成多邊形當且僅當
\[a_m<{1\over 2}\sum_{i=1}^ma_i\]
而後如今問題是如何最大化面積
有一個結論是面積最大當且僅當全部的頂點在同一個圓上,證實以下(然而我並看不懂就是了)
而後咱們如今就是須要二分這個圓的半徑,這個要分兩種狀況討論,圓心在多邊形內和多邊形外。
若是在多邊形內,那麼咱們看看當前全部木棒覆蓋的圓心角是否大於\(\pi\),若是是的話咱們須要增大半徑,不然要縮小半徑
若是在多邊形外,咱們看看\(a_1,...,a_{m-1}\)的木棒覆蓋的圓心角和\(a_m\)覆蓋的圓心角的大小之比。若是\(a_m\)覆蓋的圓心角更大,咱們須要增大半徑,不然減小半徑
而後就直接暴力子集\(dp\)就能夠了
//minamoto #include<bits/stdc++.h> #define R register #define inf 0x3f3f3f3f #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;} 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; } const int N=15,M=(1<<12)+5;const double Pi=acos(-1.0),eps=1e-15; inline int sgn(R double x){return x<-eps?-1:x>eps;} inline double sqr(R double x){return x*x;} int a[N],b[N],p[M],st[N][N],top[N];double d[M],g[M]; int n,lim,tot,ans,cnt; bool ck1(double mid){ double s=0; fp(i,1,tot-1)s+=asin(b[i]*0.5/mid); return sgn(s-asin(b[tot]*0.5/mid))>0; } bool ck2(double mid){ double s=0; fp(i,1,tot)s+=asin(b[i]*0.5/mid); return sgn(Pi-s)>0; } int main(){ // freopen("testdata.in","r",stdin); int T=read(); while(T--){ n=read();fp(i,0,n-1)a[i]=read(); sort(a,a+n),lim=(1<<n); fp(i,1,lim-1){ tot=d[i]=g[i]=cnt=0; fp(j,0,n-1)(i>>j&1)?b[++tot]=a[j],cnt+=a[j]:0; if(tot<3||cnt-b[tot]<=b[tot])continue; cnt=0; double Ri=0; if(!ck2(b[tot]*0.5)){ for(R double l=b[tot]*0.5,r=10000,mid=(l+r)*0.5;++cnt<70;mid=(l+r)*0.5) ck2(mid)?Ri=r=mid:l=mid; fp(j,1,tot)g[i]+=sqrt(sqr(Ri)-sqr(b[j])*0.25)*b[j]*0.5; }else{ for(R double l=b[tot]*0.5,r=10000,mid=(l+r)*0.5;++cnt<70;mid=(l+r)*0.5) ck1(mid)?Ri=r=mid:l=mid; fp(j,1,tot-1)g[i]+=sqrt(sqr(Ri)-sqr(b[j])*0.25)*b[j]*0.5; g[i]-=sqrt(sqr(Ri)-sqr(b[tot])*0.25)*b[tot]*0.5; } } fp(i,0,lim-1)d[i]=0; d[0]=1; fp(i,0,lim-1)if(sgn(d[i])>0) for(R int s=(lim-1)^i,j=s;j;j=(j-1)&s) if(sgn(g[j])&&cmax(d[i|j],d[i]*g[j]))p[i|j]=i; ans=1,tot=0,d[0]=0; fp(i,1,lim-1)sgn(d[i]-d[ans])>0?ans=i:0; printf("%.10lf\n",d[ans]); for(;ans;ans=p[ans])if(sgn(g[ans^p[ans]])>0){ top[++tot]=0; for(R int i=0,t=ans^p[ans];i<n;++i)(t>>i&1)?st[tot][++top[tot]]=i:0; } printf("%d\n",tot); fp(i,1,tot){ printf("%d ",top[i]); fp(j,1,top[i])printf("%d%c",a[st[i][j]]," \n"[j==top[i]]); } } return 0; }