首先显然有多少个奇数,就有多少个回文串是最优的(没有奇数时构造一个回文串
然后有了k个“核心”,把剩下的字符顺序安排到这些的两侧,最后最短的回文串长度就是答案
#include<map> #include<stack> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<complex> #include<iostream> #include<assert.h> #include<algorithm> using namespace std; #define inf 1001001001 #define infll 1001001001001001001LL #define FOR(i,a,n) for(int (i)=a;(i)<=(n);++(i)) #define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i)) #define ll long long #define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl #define gmax(a,b) (a)=max((a),(b)) #define gmin(a,b) (a)=min((a),(b)) #define ios0 ios_base::sync_with_stdio(0) #define Ri register int #define gc getchar() #define il inline il int read(){ bool f=true; Ri x=0;char ch; while(!isdigit(ch=gc))if(ch==‘-‘)f=false; while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc;} return f?x:-x; } #define gi read() #define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout); int n,a[100005]; int main(){ FO(palindromic); int T=gi; while(T--){ int cnt=0,sum=0; n=gi; FOR1(i,n){ a[i]=gi;sum+=a[i]; if(a[i]&1)cnt++; } // printf("%d %d\n",cnt,sum); if(cnt) cout<<(sum-cnt)/2/cnt*2+1<<endl; else cout<<sum<<endl; } return 0; }
上次做这题:20160430ysy出题的时候
首先任意两点的最短路只有两种情况:曼哈顿距离,曼哈顿距离+2
那么我们考虑怎样的点对曼哈顿距离会被影响
显然是下面这样的:黑色是障碍,红色和蓝点距离加2
那么我们分行列统计这样的对数,就可以(
//fyb //旅行 #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> using namespace std; typedef double ll; ll tot; ll gg; int n,m; char s[2000]; int row[1010],col[1010]; int fyb(int i,int j,int k){return 2*(i-1)*(k-j);} ll dorow(){ ll ans=0; for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) ans=ans+(m-(row[i]>0))*(m-(row[j]>0))*(j-i)/gg; for (int i=1;i<=n;i++) if (row[i]){ ans=ans+fyb(row[i],row[i],m)/gg; for(int j=i-1;j>0&&row[j]&&row[j]<row[j+1];j--) ans=ans + fyb(row[j],row[i],m)/gg; for(int j=i+1;j<=n&&row[j]&&row[j]<row[j-1];j++)ans=ans + fyb(row[j],row[i],m)/gg; } return ans; } ll docol(){ ll ans=0; for (int i=1;i<m;i++) for (int j=i+1;j<=m;j++) ans=ans+(n-(col[i]>0))*(n-(col[j]>0))*(j-i)/gg; for (int i=1;i<=m;i++) if (col[i]){ ans=ans+fyb(col[i],col[i],n)/gg; for(int j=i-1;j>0&&col[j]&&col[j]<col[j+1];j--) ans= ans + fyb(col[j],col[i],n)/gg; for(int j=i+1;j<=m&&col[j]&&col[j]<col[j-1];j++) ans=ans + fyb(col[j],col[i],n)/gg; } return ans; } int main(){ freopen("chess.in","r",stdin); freopen("chess.out","w",stdout); int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); tot=0;memset(row,0,sizeof(row));memset(col,0,sizeof(col)); for (int i=1;i<=n;i++){ scanf("%s",s); for (int j=0;j<m;j++) if (s[j]==‘G‘){ tot++; row[i]=j+1; col[j+1]=i; break; } } gg=n*m-tot; gg = gg * gg; double gg2 = dorow() + docol(); gg2 = gg2 * 2.0; printf("%.4lf\n", gg2); } return 0; }
(出现了玄学的换行
设定ans[i][j]
表示当前时刻,从i-j最早什么时候到达
首先我们发现,加上一条边只会影响这条边的起点出发的边和到达终点的边
那么我们反向加边,每次更新一些ans[i][j]
查询就变得简洁很多了。
#include<map> #include<stack> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<complex> #include<iostream> #include<assert.h> #include<algorithm> using namespace std; #define inf 1001001001 #define infll 1001001001001001001LL #define FOR0(i,n) for(int (i)=0;(i)<(n);++(i)) #define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i)) #define ll long long #define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl #define gmax(a,b) (a)=max((a),(b)) #define gmin(a,b) (a)=min((a),(b)) #define ios0 ios_base::sync_with_stdio(0) #define Ri register int #define gc getchar() #define il inline il int read(){ bool f=true; Ri x=0;char ch; while(!isdigit(ch=gc))if(ch==‘-‘)f=false; while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc;} return f?x:-x; } #define gi read() #define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout); int n,m,q,u[233333],v[233333],ans[233333]; struct data{ int a,b,c,d,id; void input(){ a=gi;b=gi;c=gi;d=gi; } }a[233333]; bool operator<(data a,data b){ return a.a<b.a; } int dis[2333][2333]; int main(){ FO(plan); n=gi;m=gi;q=gi; memset(dis,127/3,sizeof(dis)); FOR1(i,n) dis[i][i]=0; FOR1(i,m) u[i]=gi,v[i]=gi; FOR1(i,q) a[i].input(),a[i].id=i; sort(a+1,a+q+1); int t=q; for(int i=m;i>=1;i--){ dis[u[i]][v[i]]=dis[v[i]][u[i]]=i; for(int j=1;j<=n;j++) dis[u[i]][j]=min(dis[u[i]][j],max(dis[v[i]][j],i)); for(int j=1;j<=n;j++) dis[v[i]][j]=min(dis[v[i]][j],max(dis[u[i]][j],i)); while(t&&a[t].a==i){ if(dis[a[t].c][a[t].d]<=a[t].b)ans[a[t].id]=true; --t; } } for(int i=1;i<=q;i++) if(ans[i]) puts("Yes"); else puts("No"); }
原文:http://www.cnblogs.com/chouti/p/5729192.html