日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2.25-3.2 周记

發布時間:2025/7/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2.25-3.2 周记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2.25-3.2

1. 計算幾何

1.1 二維幾何基礎

struct Point{double x,y;Point(double x = 0, double y = 0):x(x),y(y){} } typedef Point Vector; Vector operator + (Vector A ,Vector B){ return Vector(A.x+B.x,A.y+B.y); } Vector operator - (Vector A ,Vector B){ return Vector(A.x-B.x,A.y-B.y); } Vector operator / (Vector A ,Vector B){ return Vector(A.x/B.x,A.y/B.y); } Vector operator * (Vector A ,Vector B){ return Vector(A.x*B.x,A.y*B.y); } bool operator < (const Point &a,const Point &b){return a.x<b.x||(a.x==b.x&&a.y<b.y); } const double eps = 1e-10; int dcmp(double x){if(fabs(x)<eps) return 0;else return x<0?-1:1; } bool operator == (const Point &a,const Point &b){return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; } //atan2計算極角

1.1.1 基本運算

double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y; } double Length(Vector A){return sqrt(Dot(A,A)); } double Angle(Vector A,Vector B){ return acos(Dot(A,B)/Length(A)/Length(B)); } double Cross(Vector A,Vector B){ return A.x*B.y - A.y*B.x;} double Area2(Point A,Point B,Point C){ return Cross(B-A,C-A); }Vector Rotate(Vector A,double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); } Vector Normal(Vector A){double L = Length(A);return Vector(-A.y/L,A.x/L); }

1.1.2 點與直線

//直線用P = P0+tv表示 //調用前確保兩條直線P+tv,Q+tw有唯一交點,當且僅當Cross(v,w)非0 Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){Vector u = P-Q;double t = Cross(w,u)/Cross(v,w);return p+v*t; }double DistanceToLine(Point P,Point A,Point B){Vector v1 = B-A,v2 = P-A;return fabs(Cross(v1,v2))/Length(v1);//不取絕對值得到有向距離 }double DistanceToSegment(Point P,Point A,Point B){if(A==B)return Length(P-A);Vector v1 = B-A,v2 = P-A,v3 = P-B;if(dcmp(Dot(v1,v2)) < 0)return Length(v2);else if(dcmp(Dot(v1,v3)) > 0)return Length(v3);else return fabs(Cross(v1,v2))/Length(v1); }//點在直線上的投影 Point GetLineProjection(Point p,Point A,Point B){Vector v = B-A;return A+v*(Dot(v,P-A)/Dot(v,v)); } //線段相交 嚴格相交 bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){double c1 = Cross(a2-a1,b1-a1),c2 = Cross(a2-a1,b2-a1);double c3 = Cross(b2-b1,a1-b1),c4 = Cross(b2-b1,a2-b1);return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; } //不嚴格相交,還沒有補充 bool Onsegment(Point p,Point a1,Point a2){return dcmp(Cross(a1-p,a2-p))==0 && dcmp(Dot(a1-p,a2-p)) < 0; }

1.1.3 多邊形

//多邊形 double ConvexPolygonArea(Point *p,int n){double area = 0;for(int i=1;i<n-1;i++)area += Cross(p[i]-p[0],p[i+1]-p[0]);return area/2; } double PolygonArea(Point *p,int n){return ConvexPolygonArea(P,n); }

1.2 與圓有關的計算問題

2. CF-1130

D題和E題

  • 火車只能順時針走
  • 一次只能從一個地方拿走一個,所以對于當前 j ,如果有cnt[j]個糖果,那么必須經過它cnt[j]次,而且把需要傳遞距離最近的那個留到最后。這樣該點需要走的最遠距離就是(cnt[j]-1)*n + last ,last為最后一個要走的距離。
  • \(O(n^2)\) 遍歷所有。輸出答案
#include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int N = 5010; int n,m,cnt[N],last[N]; int main(){cin>>n>>m;memset(last,0x3f,sizeof last);for(int i=0,a,b;i<m;i++){scanf("%d%d",&a,&b);b = (b+n-a)%n;cnt[a]++;last[a] = min(last[a],b);}for(int i=1;i<=n;i++){int res = 0;for(int j=1;j<=n;j++)if(cnt[j])res = max(res,(cnt[j]-1)*n + last[j] + (j-i+n)%n);printf("%d ",res);}puts("");return 0; }

3. CF-1038

C - Gambling

  • 這題很簡單,貪心就可以了,奈何我腦癡把數組下標寫的小了,浪費了二十分鐘

D - Slime

  • 每個數給答案的貢獻無非只有兩種,一種正的,一種負的,讓我們想想極端的情況。假如這個序列整個都是正的,那我們需要一個數來充當被減數,然后之后整個序列就可以進行運算了。當我們運算出當前結果時,可以想到的是,該結果可以進行內部取反,來迎合下一次操作。(妙啊)
#include <bits/stdc++.h> using namespace std; const int N = 500010; typedef long long ll; ll a[N]; int n; int main(){cin>>n;for(int i=1;i<=n;i++)scanf("%lld",&a[i]);if(n==1)cout<<a[1]<<endl;else{ll mi = 1e9,cnt_pos=0,cnt_neg=0,res=0;for(int i=1;i<=n;i++){mi = min(mi,abs(a[i]));res+=abs(a[i]);if(a[i]>0)cnt_pos++;else if(a[i]<0)cnt_neg++;}if(cnt_pos&&cnt_neg)cout<<res<<endl;else cout<<res-2*mi<<endl;}return 0; }

4. CF-1025

B - Weakened Common Divisor

  • 這個題差點就想出來了,然而我太著急。
  • 每組兩個數字,從中取出一個,然后整個序列很n個組,使得取出來的這n個數字的gcd不為1
  • 因為每組兩個數字都可以取,所以可以提供的質因子就變成了兩份,為了產生對答案的貢獻,我們不妨把該組可以產生的貢獻都計算進去。然后篩選出來的答案再進行壓縮,使得他符合所有組中的選擇。
  • 每組的數乘起來,然后求整個序列的gcd,可以想到這個gcd包含了所有組中共有的質因數(質因數的指數是多少不用管)。然后每次篩的時候,選一個質因數不為一的數字選就可以了。
#include <bits/stdc++.h> using namespace std; #define g std::__gcd long long A[555555],B[555555],n,a=0; int main(){scanf("%lld", &n);for(int i=1;i<=n;i++){scanf("%lld%lld",&A[i],&B[i]);a=g(a,A[i]*B[i]);}if(a==1){return puts("-1"),0;}for(int i=1;i<=n;i++){if(g(a,A[i])>1)a=g(a,A[i]);elsea=g(a,B[i]);}return printf("%lld\n", a), 0; }

C - Plasticine zebra

  • 取一個切點然后反轉,兩次反轉我們可以發現完全就是將前綴串接到了后綴串的后面,而一次反轉效果也是同樣的,把切割點分開,兩端連上,中間的情況我們不需要考慮。
  • 所以這個題就轉換為了把這個串結成一個圈,然后在圈上取一段長度最長不超過n的連續不同序列。注意極端情況(如果不是cf給的數據,恐怕要卡很久)
#include <bits/stdc++.h> using namespace std; char s[200100]; int main(){cin>>s;int res = 0, cnt = 1;int len = strlen(s);for(int i=len;i<len+len;i++)s[i] = s[i-len];for(int i=0;i<2*len-1;i++)if(s[i]==s[i+1]){res = max(res,cnt);cnt = 1;}else cnt++;res = max(res,cnt);if(res>len)cout<<len<<endl;else cout<<res<<endl;return 0; }

D - Recovering BST

  • 區間dp,思路挺順,但是有一點馬虎了之后就會造成很大的麻煩
  • dp[l][r][0]表示以 l-1 為根的區間可否組成二叉搜索樹。然后搜就可以了
  • 代碼可以優化一下
#include <bits/stdc++.h> using namespace std; const int N = 770; int n; int d[N][N][2],g[N][N],a[N]; int gcd(int a,int b){return b==0?a:gcd(b,a%b); } int dp(int l,int r,int m){int p = m==0?l-1:r+1;int &res = d[l][r][m];if(res)return res;if(l==r){if(g[l][p]>1)res = 1;else res = -1;}else{int flag = 0;for(int i=l;i<=r;i++){if(g[i][p]>1){if(i==l){if(dp(i+1,r,0)==1){flag = 1;break;}}if(i==r){if(dp(l,i-1,1)==1){flag = 1;break;}}else{if(dp(l,i-1,1)==1&&dp(i+1,r,0)==1){flag = 1;break;}}}}if(flag)res = 1;else res = -1;}return res == 1; } int main(){cin>>n;for(int i=1;i<=n;i++){scanf("%d",&a[i]);g[i][i] = a[i];}for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){g[i][j] = g[j][i] = gcd(a[i],a[j]);}if(n == 2){if(g[1][2]>1)puts("Yes");else puts("No");return 0;}int flag = 0;for(int i=1;i<=n;i++){if(i==1){if(dp(2,n,0)==1){flag = 1;break;}}else if(i==n){if(dp(1,n-1,1)==1){flag = 1;break;}}else if(dp(1,i-1,1)==1&&dp(i+1,n,0)==1){flag = 1;break;}}/*for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++)printf("%d %d %d %d\n",i,j,d[i][j][0],d[i][j][1]);}*/if(flag)puts("Yes");elseputs("No");return 0; }

壓縮后:

#include <bits/stdc++.h> using namespace std; const int N = 770; int n; int d[N][N][2],g[N][N],a[N]; int gcd(int a,int b){return b==0?a:gcd(b,a%b); } int dp(int l,int r,int m){int p = m==0?l:r;int &res = d[l][r][m];if(res)return res;if(l==r) res = 1;else{l = m==0?l+1:l;r = m==1?r-1:r;int flag = 0;for(int i=l;i<=r;i++){if(g[i][p]>1){if(dp(l,i,1)==1&&dp(i,r,0)==1){flag = 1;break;}}}if(flag)res = 1;else res = -1;}return res == 1; } int main(){cin>>n;for(int i=1;i<=n;i++){scanf("%d",&a[i]);g[i][i] = a[i];}for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){g[i][j] = g[j][i] = gcd(a[i],a[j]);}int flag = 0;for(int i=1;i<=n;i++){if(dp(1,i,1)==1&&dp(i,n,0)==1){flag = 1;break;}}if(flag)puts("Yes");else puts("No");return 0; }

5. CF-1027

B - Numbers on the Chessboard

  • 思路還是比較清晰的,不過在處理各種情況時,不要一味想著統一所有情況,其實分一下奇偶也是可以的,更容易寫對
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,q,x,y; int main(){cin>>n>>q;ll res;for(int i=1;i<=q;i++){cin>>x>>y;if((x+y)%2==0){if(x&1) res = ((x-1)/2)*n+(y/2+1);else res = ((x-2)/2)*n + ((n+1)/2)+y/2;}else {if(x&1) res = ((x-1)/2)*n + y/2 + (n*n+1)/2;else res = ((x-2)/2)*n + n/2 + y/2+1 + (n*n+1)/2;}cout<<res<<endl;}return 0; }

C - Minimum Value Rectangle

  • 雖然是個難度1600的貪心,但是貪心策略很好想,難點在于處理上,如果用hash存儲的話,即使是1e4的數組,每組test memset一下時間也會爆炸,貌似有人卡過的,不過這不是正解。
  • 正解是先排個序,然后兩個相同的變成一個,單著的就拋棄了就可以了。然后掃一次
  • T了半小時之后看正解,因為數組下標,還有循環,又坑了半小時。感覺狀態不太好的時候就不要硬干了,肯定是小問題。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1000*1000+13; int T,n,m,a[N],b[N]; int main(){scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);sort(a,a+n);int m = 0;for(int i=0;i<n-1;i++){if(a[i]==a[i+1]){b[m++] = a[i];i++;}}int A = b[0],B = b[1];ll P = (A+B)*ll(A+B);ll S = A*ll(B);for(int i=0;i<m-1;i++){ll TP = (b[i]+b[i+1])*ll(b[i]+b[i+1]);ll TS = b[i]*ll(b[i+1]);if(TS*P > S*TP){A = b[i];B = b[i+1];P = TP;S = TS;}}printf("%d %d %d %d\n",A,A,B,B);}return 0; }

D - Mouse Hunt

  • 這題一眼就是并查集,NONONO,忽略了兩點的有向關系。也是巧了,剛做了這題第二天就在牛客碰到了。
  • 具體處理就是先拓撲掃一遍,剩下的就是環,在環內找個最小值放哨兵就可以了。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 200010; int n; int c[N],p[N],deg[N],v[N];int dfs(int x){v[x] = 1;if(v[p[x]])return c[x];else return min(c[x],dfs(p[x])); } int main(){cin>>n;for(int i=1;i<=n;i++)scanf("%d",&c[i]);for(int i=1;i<=n;i++){scanf("%d",&p[i]);deg[p[i]]++;}queue<int> q;for(int i=1;i<=n;i++)if(deg[i]==0)q.push(i);while(!q.empty()){int x = q.front();q.pop();deg[p[x]]--;if(deg[p[x]]==0)q.push(p[x]);}int res = 0;for(int i=1;i<=n;i++){if(deg[i]&&!v[i]){//printf("%d\n",i);res+=dfs(i);}}cout<<res<<endl;return 0; }

6.CF-1023

A - Single Wildcard Pattern Matching

  • 被A題卡特判了。難過
#include <bits/stdc++.h> using namespace std; const int N = 200010; char s[N],t[N]; int n,m; bool check(int x){if(x==n&&n!=m)return false;for(int i=0;i<x;i++)if(s[i] != t[i])return false;for(int i=n-1;i>x;i--){int j = m-1-(n-1-i);if(j<x)return false;if(s[i] != t[j])return false;}return true; } int main(){cin>>n>>m;cin>>s>>t;if(n>m+1){puts("NO");return 0;}int index = n;for(int i=0;i<n;i++)if(s[i]=='*'){index = i;break;}if(check(index))puts("YES");else puts("NO");return 0; }

大佬的代碼:

#include <bits/stdc++.h> using namespace std; int main() {string s1,s2;int n,m,i=0;cin>>n>>m>>s1>>s2;while(s1[i]==s2[i]&&i<min(m,n))i++;while(s1[n-1]==s2[m-1]&&i<min(m,n)){n--;m--;}return cout<<(s1[i]=='*'&&n-i==1||s1==s2?"YES":"NO"),0; }

C - Bracket Subsequence

  • 直接放代碼了,這題沒什么好說的,還卡了那么久。
#include <bits/stdc++.h> using namespace std; const int N = 200010; int n,k; char s[N],t[N]; int main(){while(cin>>n>>k){cin>>s;int l = 0,r = 0,p = 0;for(int i=0;i<n;i++){if(s[i] == '('){l++;}else{r++;}putchar(s[i]);if(l == k/2)break;}for(r = r+1;r<=l;r++)putchar(')');puts("");}return 0; }

轉載于:https://www.cnblogs.com/1625--H/p/10461355.html

總結

以上是生活随笔為你收集整理的2.25-3.2 周记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。