8.11
T1 给定一个序列M,求出能过构造出的序列使得(Si+Si+1)/2=Mi成立的序列个数.保证M,S递增。
T2 平面点集中最大的四边形面积
T3 不太懂得一道国家队选拔的加强版。
90+20+10=120 三题暴力
T1写了一个非常不正确的O(n)结果拿了90,T2只想到了n^3的做法,T3暴力
Sol:
T1显然知道S中的一个数就可以知道所有的S,每个S都可以由S1和Mi来表示,那么由于S是递增的就可以列出一些很有规律的不等式,解不等式即可。
不正确的做法就是对于每三个M的差,两边的和-中间的最小值。
T2四边形肯定会有一条的对角线那么枚举对角线,在枚举对角线的两端就能做到O(n^3)
会发现答案的四边形显然会在凸包上,那么离对角线最远的点总是单调的。
T3看了不会
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #define LL long long 6 using namespace std; 7 inline void Get_Int(LL &x) 8 { 9 x=0; char ch=getchar(); 10 while (ch<'0' || ch>'9') ch=getchar(); 11 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 12 } 13 inline LL Min(LL x,LL y) {return x>y?y:x;} 14 inline LL Max(LL x,LL y) {return x>y?x:y;} 15 //======================== 16 const LL Maxn=5001000; 17 const LL Inf=(LL)1<<60; 18 LL M[Maxn],Ans,n; 19 int main() 20 { 21 Get_Int(n); 22 for (LL i=1;i<=n;i++) Get_Int(M[i]); 23 LL Ret=M[1],L=-Inf,R=M[1]; 24 for (int i=1;i<n;i++) 25 { 26 if (i&1) Ret=Ret+M[i]-M[i+1]; 27 else Ret=M[i+1]-M[i]+Ret; 28 if (i&1) L=Max(L,Ret); 29 else R=Min(R,Ret); 30 } 31 if (L>R) puts("0"); else printf("%d\n",R-L+1); 32 return 0; 33 }
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 const int Maxn=5010; 8 const double eps=1e-8; 9 struct Node 10 { 11 double x,y; 12 Node (double x=0,double y=0):x(x),y(y){} 13 }; 14 inline Node operator - (Node P,Node Q) {return Node(P.x-Q.x,P.y-Q.y);} 15 inline double Cross(Node P,Node Q) {return P.x*Q.y-P.y*Q.x;} 16 inline double Area(Node A,Node B,Node C) {return Cross(B-A,C-A);} 17 inline int dcmp(double x) {if (fabs(x)<eps) return 0; return x>0?1:-1;} 18 inline double Dis(Node O) {return sqrt(O.x*O.x+O.y*O.y);} 19 inline double Max(double x,double y) {return x>y?x:y;} 20 inline void Swap(Node &X,Node &Y) {Node T=X;X=Y;Y=T;} 21 //==================================== 22 int n,Top; 23 double Ans; 24 Node P[Maxn],V[Maxn]; 25 inline bool cmp(Node A,Node B) 26 { 27 if (dcmp(Area(P[1],A,B))==0) return Dis(A-P[1])<Dis(B-P[1]); 28 return Area(P[1],A,B)>0; 29 } 30 inline void Graham() 31 { 32 int k=1; 33 for (int i=2;i<=n;i++) 34 if (P[i].y<P[k].y || (dcmp(P[i].y-P[k].y)==0 && P[i].x<P[k].x)) k=i; 35 Swap(P[1],P[k]); 36 sort(P+2,P+n+1,cmp); 37 V[1]=P[1],V[2]=P[2]; Top=2; 38 for (int i=3;i<=n;i++) 39 { 40 while (Top>=2 && Area(V[Top-1],V[Top],P[i])<=0) Top--; 41 V[++Top]=P[i]; 42 } 43 } 44 inline void Work() 45 { 46 V[Top+1]=V[1]; Ans=0; 47 for (int X=1;X<=Top;X++) 48 { 49 int u=X%Top+1,v=(X+2)%Top+1; 50 for (int Y=X+2;Y<=Top;Y++) 51 { 52 while (u%Top+1!=Y && fabs(Area(V[X],V[Y],V[u+1]))>fabs(Area(V[X],V[Y],V[u]))) u=u%Top+1; 53 while (v%Top+1!=X && fabs(Area(V[X],V[Y],V[v+1]))>fabs(Area(V[X],V[Y],V[v]))) v=v%Top+1; 54 Ans=Max(Ans,fabs(Area(V[u],V[X],V[Y]))+fabs(Area(V[v],V[X],V[Y]))); 55 } 56 } 57 } 58 int main() 59 { 60 scanf("%d",&n); 61 for (int i=1;i<=n;i++) scanf("%lf%lf",&P[i].x,&P[i].y); 62 Graham(); 63 Work(); 64 printf("%.3lf\n",Ans/2.0); 65 return 0; 66 }
8.12 啊被虐爆了..
T1 有 M 个序列,要在每个序列里选一个元素出来,求元素总和第 K 小的值。
T2 平面上有n个凸包求两点间的最短路,不能穿过凸包。
T3 看不懂..
50+0+0=50
T1 一眼转化为第K短路模型然后50MLE了(循环队列的话应该没问题),T2 计算几何+Dij貌似出了点偏差,而且我在判断两条直线关系的时候居然是求出交点然后判断!(mdzz)
Sol:
T1 实际上非常暴力,把小根堆弹K次就行了,然后把当前的堆其中的一个序列把原来的删去,加入比他大的后一个。需要注意的是每次把所有的序列往后会有重复,所以要记录一个i,表示前1~i-1的都不能变化了
T2 M^3暴力枚举每个点判一下是否会相交即可,感觉类似于VIJOS中的有一道叫做围墙的题.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #define mp make_pair 8 #define pb push_back 9 #define fi first 10 #define se second 11 #define PA pair<int,pair<int,vector<int> > > 12 13 using namespace std; 14 inline void Get_Int(int &x) 15 { 16 x=0; char ch=getchar(); 17 while (ch<'0' || ch>'9') ch=getchar(); 18 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 19 } 20 priority_queue<PA,vector<PA>,greater<PA> > Q; 21 int m,k,a[12][500000]; 22 vector<int> V; 23 int main() 24 { 25 Get_Int(m),Get_Int(k); 26 for (int i=1;i<=m;i++) 27 { 28 Get_Int(a[i][0]); 29 for (int j=1;j<=a[i][0];j++) Get_Int(a[i][j]); 30 sort(a[i]+1,a[i]+a[i][0]+1); 31 } 32 int Ret=0; for (int i=1;i<=m;i++) Ret+=a[i][1]; 33 V.clear(); V.pb(0); for (int i=1;i<=m;i++) V.pb(1); 34 Q.push(mp(Ret,mp(1,V))); 35 for (int i=1;i<k;i++) 36 { 37 PA U=Q.top(); Q.pop(); 38 for (int j=U.se.fi;j<=m;j++) 39 { 40 U.se.se[j]++; 41 Q.push(mp(U.fi+a[j][U.se.se[j]]-a[j][U.se.se[j]-1],mp(j,U.se.se))); 42 U.se.se[j]--; 43 } 44 } 45 printf("%d\n",Q.top().fi); 46 return 0; 47 }
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #define mp make_pair 9 #define pb push_back 10 #define fi first 11 #define se second 12 #define pa pair<int,int> 13 #define PA pair<double,int> 14 using namespace std; 15 inline void Get_Int(int &x) 16 { 17 x=0; char ch=getchar(); 18 while (ch<'0' || ch>'9') ch=getchar(); 19 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 20 } 21 const int Maxn=310; 22 const double eps=1e-6; 23 int Begin[Maxn],End[Maxn],num[Maxn],tot,n,S,T; 24 double f[Maxn][Maxn],dis[Maxn]; 25 bool vis[Maxn]; 26 vector<pa> Line; 27 struct Vector 28 { 29 double x,y; 30 Vector(double x=0,double y=0):x(x),y(y){} 31 }P[Maxn]; 32 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);} 33 inline double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} 34 inline double Area(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);} 35 inline double Dis(Vector A) {return sqrt(A.x*A.x+A.y*A.y);} 36 inline int dcmp(double x) {if (fabs(x)<eps) return 0; return x>0?1:-1;} 37 inline bool Pan(int u,int v,int p,int q) 38 { 39 int s=Area(P[u],P[p],P[q]); 40 int t=Area(P[v],P[p],P[q]); 41 if (dcmp(s)*dcmp(t)==-1) return true; 42 return false; 43 } 44 inline bool Pan2(int u,int v,int p,int q) 45 { 46 int s=Area(P[u],P[p],P[q]); 47 int t=Area(P[v],P[p],P[q]); 48 if (dcmp(s)*dcmp(t)==0) return true; 49 return false; 50 } 51 inline bool Check(int u,int v) 52 { 53 for (int i=1;i<=n;i++) 54 { 55 int Cnt=0; 56 for (int j=Begin[i];j<=End[i];j++) 57 { 58 if (Pan(u,v,Line[j].fi,Line[j].se) && Pan(Line[j].fi,Line[j].se,u,v)) return false; 59 if (Pan2(u,v,Line[j].fi,Line[j].se) || Pan2(Line[j].fi,Line[j].se,u,v)) Cnt++; 60 } 61 if (Cnt>=4) return false; 62 } 63 return true; 64 } 65 priority_queue<PA,vector<PA>,greater<PA> > Q; 66 void Dij() 67 { 68 for (int i=1;i<=tot;i++) dis[i]=10000000.0; 69 memset(vis,false,sizeof(vis)); 70 dis[S]=0; 71 Q.push(mp(0.0,S)); 72 while (!Q.empty()) 73 { 74 int u=Q.top().se; Q.pop(); 75 if (vis[u]) continue; vis[u]=true; 76 for (int i=1;i<=tot;i++) 77 if (u!=i && f[u][i]!=-1 && dis[i]>dis[u]+f[u][i]) 78 { 79 dis[i]=dis[u]+f[u][i]; 80 Q.push(mp(dis[i],i)); 81 } 82 } 83 } 84 int main() 85 { 86 87 Get_Int(n); 88 Line.pb(mp(0,0)); 89 for (int i=1;i<=n;i++) 90 { 91 Get_Int(num[i]); Begin[i]=tot+1; 92 for (int j=1;j<=num[i];j++) 93 { 94 tot++; scanf("%lf%lf",&P[tot].x,&P[tot].y); 95 if (j!=1) Line.pb(mp(tot,tot-1)); 96 } 97 Line.pb(mp(tot,tot-num[i]+1)); End[i]=tot; 98 } 99 Get_Int(S),Get_Int(T); 100 for (int i=1;i<=tot;i++) 101 for (int j=1;j<=tot;j++) 102 { 103 if (i==j) {f[i][j]=0.0; continue;} 104 if (Check(i,j)) f[i][j]=Dis(P[i]-P[j]); else f[i][j]=-1; 105 } 106 Dij(); 107 printf("%.4lf\n",dis[T]); 108 return 0; 109 }
8.13
T1 定义两个函数f,g,并求出g(n)的值:f(n)为所有小于n的与n互质的数之和,g(n)为所有所有n的约数的f的和..
T2 DP 难以描述
T3 MST难以描述
30+50+30=110 三题暴力
T1
30:暴力枚举
60:然后会发现f其实可以用容斥算出来即,比如算f(60),先 O(sqrt(N))的时间,找出60的质因子有哪些。得到它的质因子2,3,5后,f(60) = 所有数的和-2的倍数的和-3的倍数的和-5的倍数的和+6(2*3)的倍数的和+10(2*5)的倍数的和+15(3*5)的倍数的和-30(2*3*5) 的倍数的和(当然这里的数都限定在60以内)。
100:有个规律及f(n)=n*φ(n)/2,Prove:(加入a与n互素呢么n-a与n也互素,反之则不互素,那么(a,n-a)的和刚好为n,而却总共有φ(n)/2对);
g(n)=∑x*φ(x)/2,因为φ具有积性可以把它分解为每个质因数的乘积即可.
T2 DP +然后用数据结构维护即可
T3
30:暴力重建MST
60:会发现重边非常多,那么对于每条重边建个卡壳就可以了。
100:奥妙重重的做法
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #define LL long long 6 using namespace std; 7 8 inline void Get_Int(LL &x) 9 { 10 x=0; char ch=getchar(); 11 while (ch<'0' || ch>'9') ch=getchar(); 12 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 13 } 14 //============================== 15 LL Kase,n,Ans; 16 inline LL Calc(LL a,LL b) 17 { 18 LL q=a*a,fr=q-a,r=1; 19 for (LL i=1;i<=b;i++) r+=fr,fr*=q; 20 return r; 21 } 22 int main() 23 { 24 freopen("shobera.in","r",stdin); 25 freopen("shobera.out","w",stdout); 26 Get_Int(Kase); 27 for (LL kase=1;kase<=Kase;kase++) 28 { 29 Get_Int(n); LL t=n; Ans=1; 30 for (LL i=2;i*i<=n;i++) 31 if (t%i==0) 32 { 33 LL Ret=0; 34 for (;t%i==0;t/=i) Ret++; 35 Ans*=Calc(i,Ret); 36 } 37 if (t>1) Ans*=Calc(t,1); 38 printf("%lld\n",(Ans+1)>>1); 39 } 40 return 0; 41 }
8.15
T1 难以表述的DP
T2 求序列第K大
T3 求分数在K进制下的有循环节长度
Sol :
T
8.17
T1 输出一定长度的升子序列
T2 数据结构,在线修改一段区间的颜色为一种颜色,询问某段区间的某个颜色个数
T3 使得a[i]>b[j]的对数
10+60+60
T1 就nlogn的发现要按照字典序输出,WA 10
T2 线段树暴力可以做到60,再大开不下了
T3 一眼网络流..mdzz 60
Sol :
T1 :那么如BZOJ1046中但是BZOJ1046中的位置,而这道题中的是权值,离散化一下就可以了。
T2 :可以有分块以时间换空间
T3 :水题贪心,拍完须后,同BZOJ1707