模版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;void solve () { } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
对浮点的处理 const double pi=acos(-1,0)//或者2*acos(0);
[!CAUTION]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 #include <bits/stdc++.h> using namespace std; #define int long long const int inf = 0x3f3f3f3f; const double EPS = 1e-8; const int MAX_DEPTH = 20; double jie(double x) { if (x <= 0 || fabs(x - round(x)) > EPS) { return -1; } int n = (int)round(x); if (x > 20) return -1; int res = 1; for (int i = n; i >= 1; i--) { res *= i; } return res; } stack<string> st; bool found = false; bool equals(double a, double b) { return fabs(a - b) < EPS; } void dfs(double x, int depth) { if (found || depth > MAX_DEPTH) { return; } if (equals(x, 3.0)) { found = true; cout << "YES\n"; cout << "操作路径: "; vector<string> path; while (!st.empty()) { path.push_back(st.top()); st.pop(); } reverse(path.begin(), path.end()); for (const auto& op : path) { cout << op << " -> "; } cout << "3\n"; return; } double next = sqrt(x); if (next > 0) { st.push("sqrt(" + to_string((int)round(x)) + ")"); dfs(next, depth + 1); if (!found) st.pop(); else return; } next = ceil(x); if (next != x) { st.push("ceil(" + to_string(x) + ")"); dfs(next, depth + 1); if (!found) st.pop(); else return; } // 尝试阶乘操作 next = jie(x); if (next != -1) { st.push("jie(" + to_string((int)round(x)) + ")"); dfs(next, depth + 1); if (!found) st.pop(); else return; } } void solve() { dfs(4.0, 0); } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; // cin >> t; while (t--) { solve(); } return 0; } #include <bits/stdc++.h> using namespace std; #define int long long const int inf=0x3f3f3f3f,N = 1e6 + 5,MAX_Depth=20; const double eps=1e-8; bool equal(double a,double b){ return fabs(a-b)<eps; } stack<string>st; double jie(double x){ if(x<=0||fabs(x-round(x)>eps))return -1; int n=(int)round(x); if(x>20)return -1; int res=1; for(int i=n;i>=1;i--){ res*=i; } return res; } void dfs(double x,int dep){ if(dep>MAX_Depth)return; if(equal(x,3.0)){ queue<string>q; while(!st.empty()){ q.push(st.top()); st.pop(); } cout<<"3 :"; while(!q.empty()){ cout<<q.front()<<"-->"; q.pop(); } exit(0); } double next=sqrt(x); if(next>0){ st.push("sqrt"); dfs(next,dep+1); st.pop(); } next=ceil(x); if(next!=x){ st.push("ceil"); dfs(next,dep+1); st.pop(); } next=jie(x); if(next!=-1){ st.push("jie"); dfs(next,dep+1); st.pop(); } } void solve(){ dfs(4.0,0); } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t=1; // cin>>t; while(t--){ solve(); } return 0; }
取模/同余原理/求逆元 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 a ^ b % p = ((a % p)^b) % p (A + B) % mod = ((A % mod) + (B % mod)) % mod (A * B) % mod = ((A % mod) * (B % mod)) % mod (A - B) % mod =((A % mod) - (B % mod) +mod) % mod (A / B) % mod = ((A % mod) * (inv (B) % mod)) % mod LL qkpow (LL a,LL p,LL mod) { LL t=1 ,tt=a%mod; while (p) { if (p&1 )t=t*tt%mod; tt=tt*tt%mod; p>>=1 ; } return t; } LL getInv (LL a,LL mod) { return qkpow (a,mod-2 ,mod); }
878. 第 N 个神奇数字 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public :long long mod=1e9 +7 ; int nthMagicalNumber (int n, int a, int b) { long long mid; long long l=0 ,r=(long long )n*min (a,b); long long gcd=__gcd(a,b); long long lcm=a/gcd*b; while (l<=r){ mid=(l+r)>>1 ; if ((mid/a+mid/b-mid/lcm)>=n){ r=mid-1 ; }else { l=mid+1 ; } } return (int )(l%mod); } };
异或运算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1. 袋子里一共a个白球,b个黑球,每次从袋子里拿2 个求,每个球每次被拿出的机会均等,如果拿出的是2 个白球或者2 个黑球,那么就往袋子里重新放入1 个白球,如果拿出的是1 个白球和1 个黑球,那么就往袋子里重新放入一个黑球,那么最终袋子里只会剩下一个球,请问最终的球是黑的概率是多少? 黑球:1 白球:0 最终球的颜色取决于:黑球数量为奇数概率100 % 黑球数量为偶数概率0 % 2. 异或运算:数值交换 在数组中保证a,b为两个下标不同的数 a=a^b; b=a^b; a=a^b; 3. 一个数异或上它的相反数:可以得到它仅保留最右侧1 的数字状态 4. 找在一个数组中出现奇数次数的a和奇数次数的b 先所有异或:得到a^b这个结果 (a^b)^(~(a^b)) 这个结果必然存在某个x数位上为1 ,故我们再次将数组分为x数位上为1 和不为1 的,遍历数位x上为1 的数最后的结果即为a,b=a^b^a;
位运算 201. 数字范围按位与 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 class Solution {public : int rangeBitwiseAnd (int left, int right) { while (left<right){ right-=(right&-right); } return right; } };
190. 颠倒二进制位 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : uint32_t reverseBits (uint32_t n) { n = ((n & 0xaaaaaaaa ) >> 1 ) | ((n & 0x55555555 ) << 1 ); n = ((n & 0xcccccccc ) >> 2 ) | ((n & 0x33333333 ) << 2 ); n = ((n & 0xf0f0f0f0 ) >> 4 ) | ((n & 0x0f0f0f0f ) << 4 ); n = ((n & 0xff00ff00 ) >> 8 ) | ((n & 0x00ff00ff ) << 8 ); n = (n >> 16 ) | (n << 16 ); return n; } };
461. 汉明距离 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : int hammingDistance (int x, int y) { return solve (x^y); } int solve (int x) { x=(x&0x55555555 )+((x>>1 )&0x55555555 ); x=(x&0x33333333 )+((x>>2 )&0x33333333 ); x=(x&0x0f0f0f0f )+((x>>4 )&0x0f0f0f0f ); x=(x&0x00ff00ff )+((x>>8 )&0x00ff00ff ); x=(x&0x0000ffff )+((x>>16 )&0x0000ffff ); return x; } };
1.贪心 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e4 + 5 ;void solve () { int n,a; cin>>n; priority_queue<int ,vector<int >,greater<int >> pq; for (int i=1 ;i<=n;i++){ cin>>a; pq.push (a); } int ans=0 ; while (pq.size ()>1 ){ int x=pq.top (); pq.pop (); int y=pq.top (); pq.pop (); ans+=x+y; pq.push (x+y); } cout<<ans<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;void solve () { string s; int k; cin>>s>>k; stack<char > st; char x; for (int i=0 ;i<s.size ();i++){ if (!st.empty ())x=st.top (); else { st.push (s[i]); continue ; } if (s[i]<x&&k>0 ){ st.pop (); k--; i--; } else st.push (s[i]); } while (k--){ st.pop (); } stack<char > st1; while (!st.empty ()){ st1. push (st.top ()); st.pop (); } while (!st1. empty ()&&st1. top ()=='0' ){ st1. pop (); } string ans="" ; if (st1. empty ()){ cout<<0 <<endl; return ; } while (!st1. empty ()){ ans+=st1. top (); st1. pop (); } cout<<ans<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;void solve () { int n,m,first=0 ; cin>>n>>m; string s,t; cin>>s>>t; for (int i=0 ;i<m;i++){ if (t[i]=='1' ){ first=i; break ; } } int len = m-first-1 ; int ans=0 ; for (int i=0 ;i<n;i++){ if (s[i]=='1' &&i+len<n){ ans++; for (int j=first;j<m;j++){ if (t[j]==s[i+j-first]){ s[i+j-first]='0' ; }else s[i+j-first]='1' ; } } } for (int i=0 ;i<n;i++){ if (s[i]=='1' ){ cout<<"-1\n" ; return ; } } cout<<ans<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 2e6 + 5 ;int a[N], pos[N];void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++){ cin>>a[i]; pos[a[i]]=i; } int ans=1 ,mn=pos[n],mx=pos[n]; for (int i=n-1 ;i>=1 ;i--){ mn=min (mn,pos[i]),mx=max (mx,pos[i]); ans=max (ans,mx-mn+1 -(n-i-1 )); } cout<<ans<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 5e5 + 5 ;int n,a,b;int w[N];bool check (int x) { int cnt=0 ; for (int i=1 ;i<=n;i++){ int re=max (0ll ,w[i]-x*a); if (re==0 )continue ; cnt+=re/b+(re%b==0 ?0 :1 ); if (cnt>x)return false ; } return true ; } void solve () { cin>>n>>a>>b; for (int i=1 ;i<=n;i++)cin>>w[i]; int l=0 ,r=5e5 +1 ; while (l<=r){ int mid=l+(r-l)/2 ; if (check (mid)){ r=mid-1 ; } else { l=mid+1 ; } } cout<<l<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
2.01背包 搞清楚谁是容积谁是价值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e2 + 5 ;int ttime[N],val[N],dp[1005 ];void solve () { int t,m; cin>>t>>m; for (int i=1 ;i<=m;i++){ cin>>ttime[i]>>val[i]; } for (int i=1 ;i<=m;i++){ for (int j=t;j>=ttime[i];j--){ dp[j]=max (dp[j],dp[j-ttime[i]]+val[i]); } } cout<<dp[t]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 3e4 + 5 ;int w[30 ],v[30 ],dp[N];void solve () { int n,m; cin>>n>>m; for (int i=1 ;i<=m;i++){ cin>>w[i]>>v[i]; v[i]=w[i]*v[i]; } for (int i=1 ;i<=m;i++){ for (int j=n;j>=w[i];j--){ dp[j]=max (dp[j],dp[j-w[i]]+v[i]); } } cout<<dp[n]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e3 + 5 ;int a[N],dp[10005 ];void solve () { int n,m,p; cin>>n>>m; for (int i=1 ;i<=n;i++){ cin>>a[i]; } dp[0 ]=1 ; for (int i=1 ;i<=n;i++){ for (int j=m;j>=a[i];j--){ dp[j]=dp[j]+dp[j-a[i]]; } } cout<<dp[m]<<"\n" ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int a[1005 ],dp[1005 ];void solve () { int s; cin>>s; for (int i=1 ;i<=s;i++){ for (int j=1 ;j<i;j++){ if (i%j==0 ){ a[i]+=j; } } } for (int i=1 ;i<=s;i++){ for (int j=s;j>=i;j--){ dp[j]=max (dp[j],dp[j-i]+a[i]); } } cout<<dp[s]<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 400 + 5 ;int dp[N][N];struct node { int h,t,k; }a[55 ]; void solve () { int H,T,n; cin>>H>>T>>n; for (int i=1 ;i<=n;i++){ cin>>a[i].h>>a[i].t>>a[i].k; } for (int i=1 ;i<=n;i++){ for (int j=H;j>=a[i].h;j--){ for (int x=T;x>=a[i].t;x--){ dp[j][x]=max (dp[j][x],dp[j-a[i].h][x-a[i].t]+a[i].k); } } } cout<<dp[H][T]<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
3.最短路 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 int dis[N],vis[N],f[N][N];void dijkstra () { memset (dis,inf,sizeof (dis)); dis[s]=0 ; for (int i=1 ; i<=n; i++) { int t=-1 ; for (int j=1 ; j<=n; j++) if (!vis[j] && (t==-1 || dis[j]<dis[t])) t=j; vis[t]=1 ; for (int j=1 ; j<=n; j++) { dis[j] = min (dis[j],dis[t]+f[t][j]); } } } int dis[N],vis[N];vector<pair<int , int >> g[N]; struct Node { int x, w; bool operator <(const Node& u) const { return w == u.w ? x < u.x : w > u.w; } }; priority_queue<Node> pq; void dijkstra (int st) { memset (dis, inf, sizeof (dis)); memset (vis, 0 , sizeof (vis)); pq.push ({st, dis[st] = 0 }); while (!pq.empty ()) { auto [x, w] = pq.top (); pq.pop (); if (vis[x]) continue ; vis[x] = 1 ; for (const auto &[y, dw] : g[x]) { if (dis[x] + dw < dis[y]) { dis[y] = dis[x] + dw; pq.push ({y, dis[y]}); } } } } int dis[N],vis[N];vector<pair<int , int > > g[N]; struct Node { int x, w; bool operator <(const Node& u) const { return w == u.w ? x < u.x : w > u.w; } }; priority_queue<Node> pq; void dijkstra (int st) { memset (dis, inf, sizeof (dis)); memset (vis, 0 , sizeof (vis)); pq.push ({st, dis[st] = 0 }); while (!pq.empty ()) { int x= pq.top ().x; pq.pop (); if (vis[x]) continue ; vis[x] = 1 ; for (int i=0 ;i<g[x].size ();i++) { int y=g[x][i].first; int dw=g[x][i].second; if (dis[x] + dw < dis[y]) { dis[y] = dis[x] + dw; pq.push ({y, dis[y]}); } } } } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int dis[10005 ],vis[10005 ],f[10001 ][10001 ];int n,s=1 ;void dijkstra () { memset (dis,inf,sizeof (dis)); dis[s]=0 ; for (int i=1 ; i<=n; i++) { int t=-1 ; for (int j=1 ; j<=n; j++) if (!vis[j] && (t==-1 || dis[j]<dis[t])) t=j; vis[t]=1 ; for (int j=1 ; j<=n; j++) { dis[j] = min (dis[j],dis[t]+f[t][j]); } } } void solve () { cin>>n; for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ if (i==j) f[i][j]=0 ; else f[i][j]=inf; } } for (int i=1 ;i<=n-1 ;i++){ for (int j=i+1 ;j<=n;j++){ cin>>f[i][j]; } } dijkstra (); cout<<dis[n]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 2e2 + 5 ;int dis[N],vis[N];vector<pair<int , int >> g[N]; struct Node { int x, w; bool operator <(const Node& u) const { return w == u.w ? x < u.x : w > u.w; } }; priority_queue<Node> pq; void dijkstra (int st) { memset (dis, inf, sizeof (dis)); memset (vis, 0 , sizeof (vis)); pq.push ({st, dis[st] = 0 }); while (!pq.empty ()) { auto [x, w] = pq.top (); pq.pop (); if (vis[x]) continue ; vis[x] = 1 ; for (const auto &[y, dw] : g[x]) { if (dis[x] + dw < dis[y]) { dis[y] = dis[x] + dw; pq.push ({y, dis[y]}); } } } } void solve () { int n,w; cin>>n; for (int i=1 ;i<=n-1 ;i++){ for (int j=i+1 ;j<=n;j++){ cin>>w; g[i].push_back ({j,w}); } } dijkstra (1 ); cout<<dis[n]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e3 + 5 ;int dis[N],vis[N];vector<pair<int , int >> g[N]; struct Node { int x, w; bool operator <(const Node& u) const { return w == u.w ? x < u.x : w > u.w; } }; priority_queue<Node> pq; void dijkstra (int st) { memset (dis, inf, sizeof (dis)); memset (vis, 0 , sizeof (vis)); pq.push ({st, dis[st] = 0 }); while (!pq.empty ()) { auto [x, w] = pq.top (); pq.pop (); if (vis[x]) continue ; vis[x] = 1 ; for (const auto &[y, dw] : g[x]) { if (dis[x] + dw < dis[y]) { dis[y] = dis[x] + dw; pq.push ({y, dis[y]}); } } } } void solve () { int n,m,u,v,w; cin>>n>>m; for (int i=1 ;i<=m;i++){ cin>>u>>v>>w; g[u].push_back ({v,w}); } dijkstra (1 ); int ans=0 ; for (int i=2 ;i<=n;i++){ ans+=dis[i]; } for (int i=2 ;i<=n;i++){ dijkstra (i); ans+=dis[1 ]; } cout<<ans<<"\n" ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
4.区间求中位数:前缀和+哈希表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 2e3 + 5 ;int a[N],sum[N],s[2 *N];void solve () { int n,ans=0 ; cin>>n; for (int i=1 ;i<=n;i++) cin>>a[i]; for (int i=1 ;i<=n;i++){ memset (s,0 ,sizeof (s)); for (int j=1 ;j<=n;j++){ if (a[j]<a[i]){ sum[j]=sum[j-1 ]+(-1 ); }else if (a[j]>a[i]){ sum[j]=sum[j-1 ]+1 ; }else { sum[j]=sum[j-1 ]; } } sum[0 ]=0 ; for (int j=0 ;j<i;j++){ s[sum[j]+2001 ]+=j+1 ; } for (int j=i;j<=n;j++){ ans+=j*s[sum[j]+2001 ]*a[i]; } } cout<<ans<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
5.二分 最大值最小化,最小值最大化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 int binary_search (int l,int r,int x) { while (l<=r){ int mid=(l+r)/2 ; if (a[mid]==x){ return mid; } else if (a[mid]>x){ r=mid-1 ; } else { l=mid+1 ; } } return -1 ; } int binary_search (int l,int r,int x) { while (l<r){ int mid=l+(r-l)/2 ; if (check (mid)){ r=mid; }else { l=mid+1 ; } } if (a[l]==x)return l; return -1 ; } int binary_search (int l,int r,int x) { while (l<r){ int mid=l+(r-l)/2 ; if (check (mid)){ l=mid; }else { r=mid-1 ; } } if (a[l]==x)return l; return -1 ; } double bsearch (double l, double r) { const double eps = 1e-6 ; while (r - l > eps) { double mid = (l + r) / 2 ; if (check (mid)) r = mid; else l = mid; } return l; } int l=0 ,r=100000000 ;while (l<=r){ int mid=(l+r)/2 ; if (judge (mid)) l=mid+1 ; else r=mid-1 ; } cout<<r; #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int a[N];int n,k;bool judge (int x) { int ans=0 ; for (int i=1 ;i<=n;i++){ ans+=a[i]/x; } if (ans>=k) return true ; else return false ; } int binary_search (int l,int r) { while (l<=r){ int mid=(l+r)/2 ; if (mid==0 ) break ; if (judge (mid)) l=mid+1 ; else r=mid-1 ; } return r; } void solve () { cin>>n>>k; double b; for (int i=1 ;i<=n;i++) { cin>>b; a[i]=(int )(b*100 ); } int ans=binary_search (0 ,10000000 ); printf ("%0.2f" ,ans/100.0 ); } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;int a[N];int n,m;bool check (int x) { int sum=0 ,cnt=1 ; for (int i=1 ;i<=n;i++){ if (a[i]+sum>x){ sum=a[i]; cnt++; }else { sum+=a[i]; } } if (cnt>m) return true ; return false ; } void solve () { cin>>n>>m; int r=0 ,l=0 ; for (int i=1 ;i<=n;i++){ cin>>a[i]; r+=a[i]; l=max (l,a[i]); } while (l<=r){ int mid=l+(r-l)/2 ; if (check (mid)){ l=mid+1 ; }else { r=mid-1 ; } } cout<<l<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;int a[N];int m,k;bool check (int x) { int sum=0 ,cnt=1 ; for (int i=1 ;i<=m;i++){ if (a[i]+sum>x){ sum=a[i]; cnt++; }else { sum+=a[i]; } } if (cnt>k) return true ; return false ; } void solve () { cin>>m>>k; int r=0 ,l=0 ; for (int i=1 ;i<=m;i++){ cin>>a[i]; r+=a[i]; l=max (l,a[i]); } while (l<=r){ int mid=l+(r-l)/2 ; if (check (mid)){ l=mid+1 ; }else { r=mid-1 ; } } stack<pair<int ,int > >st; int sum=0 ,ansr=m; for (int i=m;i>=1 ;i--){ if (a[i]+sum==l){ sum=0 ; st.push ({i,ansr}); ansr=i-1 ; }else if (a[i]+sum>l){ sum=a[i]; st.push ({i+1 ,ansr}); ansr=i; }else { sum+=a[i]; if (i==1 ){ st.push ({i,ansr}); } } } while (!st.empty ()){ auto [l,r]=st.top (); st.pop (); cout<<l<<" " <<r<<endl; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e4 +5 ;int n,m,s,t;int vis[N];vector<pair<int ,int >>g[N]; bool check (int x) { memset (vis,0 ,sizeof (vis)); queue<int >q; q.push (s); vis[s]=1 ; while (!q.empty ()){ int u=q.front (); if (u==t)return true ; q.pop (); for (auto [v,w]:g[u]){ if (vis[v])continue ; if (w>x)continue ; q.push (v);vis[v]=1 ; } } return false ; } void solve () { cin>>n>>m>>s>>t; int l=0 ,r=0 ; for (int i=1 ;i<=m;i++){ int u,v,w; cin>>u>>v>>w; r=max (r,w); g[u].push_back ({v,w}); g[v].push_back ({u,w}); } while (l<=r){ int mid = (l+r)>>1 ; if (check (mid)){ r=mid-1 ; } else { l=mid+1 ; } } cout<<l<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 2e2 + 5 ;int n,m;struct node { int v,c; double val; bool operator <(const node &a)const { return val<a.val; } }a[N]; bool check (double x) { for (int i=1 ;i<=n;i++)a[i].val=x*a[i].c-a[i].v; sort (a+1 ,a+1 +n); double sum=0 ; for (int i=1 ;i<=m;i++){ sum+=a[i].val; } return sum<=0 ; } void solve () { cin>>n>>m; for (int i=1 ;i<=n;i++)cin>>a[i].v; for (int i=1 ;i<=n;i++)cin>>a[i].c; double l=0 ,r=1000 ; while (r-l>1e-6 ){ double mid=(l+r)/2 ; if (check (mid)){ l=mid; }else { r=mid; } } cout<<fixed<<setprecision (3 )<<l<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 50 + 5 ;int n;int bseach[N];vector<pair<int ,int >>v (N); int find (int x) { if (bseach[x]==x)return x; return bseach[x]=find (bseach[x]); } bool check (int x) { for (int i=0 ;i<n;i++){ for (int j=i+1 ;j<n;j++){ int a=abs (v[i].first - v[j].first); int b=abs (v[i].second - v[j].second); if (a+b<=2 *x){ int fa=find (i),fb=find (j); if (fa!=fb){ bseach[fa]=fb; } } } } int cnt=0 ; for (int i=0 ;i<n;i++){ if (bseach[i]==i){ cnt++; } } if (cnt==1 ){ return true ; }else { return false ; } } void solve () { cin>>n; for (int i=0 ;i<n;i++){ cin>>v[i].first>>v[i].second; } int l=0 ,r=1e9 +10 ; while (l<=r){ int mid=l+(r-l)/2 ; for (int i=0 ;i<n;i++){ bseach[i]=i; } if (check (mid)){ r=mid-1 ; }else { l=mid+1 ; } } cout<<l<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 5e5 + 5 ;int n,a,b;int w[N];bool check (int x) { int cnt=0 ; for (int i=1 ;i<=n;i++){ int re=max (0ll ,w[i]-x*a); if (re==0 )continue ; cnt+=re/b+(re%b==0 ?0 :1 ); if (cnt>x)return false ; } return true ; } void solve () { cin>>n>>a>>b; for (int i=1 ;i<=n;i++)cin>>w[i]; int l=0 ,r=5e5 +1 ; while (l<=r){ int mid=l+(r-l)/2 ; if (check (mid)){ r=mid-1 ; } else { l=mid+1 ; } } cout<<l<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
6.双指针+模拟 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int a[N],b[2005 ],cnt;void in (int x) { if (b[x]==0 )cnt++; b[x]++; } void d (int x) { if (b[x]==1 )cnt--; b[x]--; } void solve () { int n,m; cin>>n>>m; for (int i=1 ;i<=n;i++){ cin>>a[i]; } int l=1 ,ans=inf,ansl=1 ,ansr=n; for (int i=1 ;i<=n;i++){ in (a[i]); while (true ){ d (a[l]); if (cnt==m)l++; else { in (a[l]); break ; } } if (cnt==m&&i-l+1 <ans)ans=i-l+1 ,ansl=l,ansr=i; } cout<<ansl<<" " <<ansr<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
7.最小生成树 Kruskal算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 struct Edge { int x, y, c; bool operator < (const Edge &u) const { return c < u.c; } }; int pre[N];int root (int x) { return pre[x] == x ? x : root (pre[x]); } void solve () { int n, m; cin >> n >> m; vector<Edge> es; for (int i = 1 ; i <= m; ++ i) { int x, y, c; cin >> x >> y >> c; es.push_back ({x, y, c}); } sort (es.begin (), es.end ()); for (int i = 1 ; i <= n; ++ i) pre[i] = i; int ans = 0 ; for (const auto & [x, y, c] : es) { if (root (x) == root (y)) continue ; ans = max (ans, c); pre[root (x)] = root (y); } cout << ans << '\n' ; } #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;struct Edge { int x, y, c; bool operator < (const Edge &u) const { return c < u.c; } }; int pre[N];int root (int x) { return pre[x] == x ? x : root (pre[x]); } void solve () { int n; cin >> n ; vector<Edge> es; vector<pair<int ,int >>d; for (int i = 0 ; i < n; ++ i) { int x, y; cin >> x >> y; d.push_back ({x,y}); } for (int i = 0 ; i < n; ++ i) { for (int j=i+1 ;j<n;++j){ int c = (abs (d[i].first - d[j].first)+abs (d[i].second - d[j].second)+1 )/2 ; es.push_back ({i, j, c}); } } sort (es.begin (), es.end ()); for (int i = 0 ; i < n; ++ i) pre[i] = i; int ans = 0 ; for (const auto & [x, y, c] : es) { if (root (x) == root (y)) continue ; ans = max (ans, c); pre[root (x)] = root (y); } cout << ans << '\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
Prim算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 struct Edge { ll x, c; bool operator < (const Edge &u) const { return c == u.c ? x > u.x : c < u.c; } }; vector<Edge> g[N]; ll d[N]; int n, m;int prim () { priority_queue<Edge> pq; bitset<N> vis; d[1 ] = 0 ; pq.push ({1 , d[1 ]}); ll res = 0 ; while (pq.size ()) { int x = pq.top ().x; pq.pop (); if (vis[x]) continue ; vis[x] = true ; res = max (res, d[x]); for (const auto &[y, w] : g[x]) { if (!vis[y]) { d[y] = min (d[y], w); pq.push ({y, d[y]}); } } } return res; }
8.并查集 1 2 3 4 int root (int x) { if (pre[x] == x) return x; return root (pre[x]); }
路径压缩优化 1 2 3 int root (int x) { return pre[x] = (pre[x] == x ? x : root (pre[x])); }
合并操作 1 2 3 4 5 6 7 8 9 10 11 12 13 void merge (int x, int y) { int rx = root (x), ry = root (y); if (rx == ry) return ; if (siz[rx] > siz[ry]) swap (rx, ry); pre[rx] = ry; siz[ry] += siz[rx]; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Solution {public :int father[1001 ];int siz[1001 ];int mpx[10001 ];int mpy[10001 ]; int root (int x) { return father[x] = (father[x] == x ? x : root (father[x])); } void merge (int x,int y) { int rx=root (x),ry=root (y); if (rx==ry)return ; if (siz[rx]>siz[ry])swap (rx,ry); father[rx]=ry; siz[ry]+=siz[rx]; } int removeStones (vector<vector<int >>& stones) { int n=stones.size (); for (int i=1 ;i<=n;i++){ father[i]=i; } for (int i=0 ;i<n;i++){ int x=stones[i][0 ]; int y=stones[i][1 ]; if (mpx[x]==0 ){ mpx[x]=i+1 ; }else { merge (mpx[x],i+1 ); } if (mpy[y]==0 ){ mpy[y]=i+1 ; }else { merge (mpy[y],i+1 ); } } int ans=0 ; for (int i=1 ;i<=n;i++){ if (father[i]==i)ans++; } return n-ans; } };
//需要在合并的时候判断:
若两个集合的father相同那么就判一下他们father的siz集合个数是否达到n,
若两个集合的father不同,那么就一定没有实现所有元素在一个集合,故对他们进行合并.合并后在判断是否集合个数达到n,即所有元素在同一个集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;struct node { int x,y,t; }arr[N]; bool cmp (node a,node b) { return a.t<b.t; } int father[1005 ],siz[1005 ],n,m;;int root (int x) { if (x==father[x])return x; return father[x]=root (father[x]); } bool merge (int x,int y) { int fx=root (x),fy=root (y); if (fx==fy){ if (siz[fx]==n){ return true ; } return false ; } if (siz[fx]>siz[fy]){ swap (fx,fy); } father[fx]=fy; siz[fy]+=siz[fx]; if (siz[fy]==n){ return true ; } return false ; } void solve () { cin>>n>>m; for (int i=1 ;i<=m;i++){ cin>>arr[i].x>>arr[i].y>>arr[i].t; } sort (arr+1 ,arr+m+1 ,cmp); for (int i=1 ;i<=n;i++){ father[i]=i; siz[i]=1 ; } for (int i=1 ;i<=m;i++){ if (merge (arr[i].x,arr[i].y)){ cout<<arr[i].t<<endl; return ; } } cout<<-1 <<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
//思路就是:将能够相交的划分为一组,然后将存放坐标的数组依据z值从小到大排序,l从小到大跑,rr从大到小跑,如果满足arr[l].z-r<=0并且arr[rr].z+r>=h则说明上下连通,接着判断二者是否连通即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e3 + 5 ;struct node { int x,y,z,id; } arr[N]; bool cmp (node a,node b) { return a.z<b.z; } int father[N],siz[N];int root (int x) { if (father[x]==x)return x; return father[x]=root (father[x]); } void merge (int x,int y) { int fx=root (x),fy=root (y); if (fx==fy)return ; if (siz[fx]>siz[fy]){ swap (fx,fy); } father[fx]=fy; siz[fy]+=siz[fx]; } void solve () { memset (father,0 ,sizeof (father)); memset (siz,0 ,sizeof (siz)); int n,h,r; cin>>n>>h>>r; for (int i=1 ;i<=n;i++){ cin>>arr[i].x>>arr[i].y>>arr[i].z; father[i]=i; siz[i]=1 ; arr[i].id=i; } for (int i=1 ;i<=n;i++){ for (int j=i+1 ;j<=n;j++){ if (abs ((arr[i].x-arr[j].x)*(arr[i].x-arr[j].x)+(arr[i].y-arr[j].y)*(arr[i].y-arr[j].y)+(arr[i].z-arr[j].z)*(arr[i].z-arr[j].z))<=4 *r*r){ merge (i,j); } } } sort (arr+1 ,arr+1 +n,cmp); for (int l=1 ;l<=n;l++){ for (int rr=n;rr>=l;rr--){ if ((arr[l].z-r)<=0 &&(arr[rr].z+r>=h)){ if (root (arr[l].id)==root (arr[rr].id)){ cout<<"Yes\n" ; return ; } }else { break ; } } } cout<<"No\n" ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
//这道题我忽略的点:
只有两所监狱
//所以怨气值越大的肯定就越要分开,所以对怨气值进行从大到小的排序,
//从大到小遍历怨气值,如果遍历到的两个犯人已经被分配到同一个监狱则输出二人的怨气值即可
//若没有被分配到同一个监狱,他们互为敌人,则分别将他们敌人的敌人与他们自己合并(分配到同一个监狱),
//用b[i]记录i的敌人代表(开始b[i]为0,则将第一个敌人赋给b[i])
[!CAUTION]
当m=1时需进行特判,原因是因为它并没有机会在循环中输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int f[20005 ],e[20005 ];struct node { int a,b,c; }arr[100005 ]; bool cmp (node a,node b) { return a.c>b.c; } int find (int x) { if (f[x]==x)return x; return f[x]=find (f[x]); } void merge (int x,int y) { int fx=find (x),fy=find (y); if (fx==fy)return ; f[fx]=fy; } void solve () { int n,m; cin>>n>>m; for (int i=1 ;i<=m;i++){ cin>>arr[i].a>>arr[i].b>>arr[i].c; } if (m==1 ){ cout<<0 <<'\n' ; return ; } for (int i=1 ;i<=n;i++){ f[i]=i; } sort (arr+1 ,arr+1 +m,cmp); for (int i=1 ;i<=m;i++){ if (find (arr[i].a)==find (arr[i].b)){ cout<<arr[i].c<<endl; return ; }else { if (!e[arr[i].a]){ e[arr[i].a]=arr[i].b; }else { merge (arr[i].b,e[arr[i].a]); } if (!e[arr[i].b]){ e[arr[i].b]=arr[i].a; }else { merge (arr[i].a,e[arr[i].b]); } } } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
//这道题给我的教训是:
我的贪心的思维很差
//贪心思路(+离线思路):
先把k值大的数量统计(该合并的合并),则k值小的包含k值大的答案
遍历r的思路是:
从大到小,则每次的r都是各点到其他点的最小可能r(其他比r大的R所关联的点已连接)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;struct node1 { int p,q,r; }arr[N]; struct node2 { int k,v,id; }brr[N]; int ans[N];bool cmp1 (node1 a,node1 b) { return a.r>b.r; } bool cmp2 (node2 a,node2 b) { return a.k>b.k; } int pre[N],siz[N];int root (int x) { return pre[x] = (pre[x] == x ? x : root (pre[x])); } void merge (int x, int y) { int rx = root (x), ry = root (y); if (rx == ry) return ; if (siz[rx] > siz[ry]) swap (rx, ry); pre[rx] = ry; siz[ry] += siz[rx]; } void solve () { int N,Q; cin>>N>>Q; for (int i=1 ;i<N;i++){ cin>>arr[i].p>>arr[i].q>>arr[i].r; } for (int i=1 ;i<=Q;i++){ cin>>brr[i].k>>brr[i].v; brr[i].id=i; } for (int i=1 ;i<=N;i++){ pre[i]=i; siz[i]=1 ; } sort (arr+1 ,arr+1 +N,cmp1); sort (brr+1 ,brr+1 +Q,cmp2); int j=1 ; for (int i=1 ;i<=Q;i++){ while (j<N&&arr[j].r>=brr[i].k){ merge (arr[j].p,arr[j].q); j++; } ans[brr[i].id]=siz[root (brr[i].v)]; } for (int i=1 ;i<=Q;i++){ cout<<ans[i]-1 <<"\n" ; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
[P2024 NOI2001] 食物链 - 洛谷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <cstdio> inline int read () { char c = getchar (); int n = 0 ; while (c < '0' || c > '9' ) { c = getchar (); } while (c >= '0' && c <= '9' ) { n = (n << 1 ) + (n << 3 ) + (c & 15 ); c = getchar (); } return n; } const int maxN = 100005 ;int n, m, ans, fa[maxN * 3 ];int find (int u) { return fa[u] == u ? u : fa[u] = find (fa[u]); }int main () { n = read (), m = read (); for (int i = 1 ; i <= n * 3 ; i++) { fa[i] = i; } for (; m; m--) { int opt = read (), u = read (), v = read (); if (u > n || v > n) { ans++; continue ; } if (opt == 1 ) { if (find (u + n) == find (v) || find (u) == find (v + n)) { ans++; } else { fa[find (u)] = find (v); fa[find (u + n)] = find (v + n); fa[find (u + n + n)] = find (v + n + n); } } else { if (find (u) == find (v) || find (u) == find (v + n)) { ans++; } else { fa[find (u + n)] = find (v); fa[find (u + n + n)] = find (v + n); fa[find (u)] = find (v + n + n); } } } printf ("%d\n" , ans); return 0 ; }
9.思维题 (1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int n,x[100 ],y[100 ];int dis (int x1,int y1,int x2,int y2) { return abs (x1-x2)+abs (y1-y2); } void solve () { int x0,y0,ax,ay,bx,by,xs,ys,t,ans=0 ; cin>>x0>>y0>>ax>>ay>>bx>>by>>xs>>ys>>t; x[0 ]=x0,y[0 ]=y0; while (++n){ x[n]=ax*x[n-1 ]+bx; y[n]=ay*y[n-1 ]+by; if (x[n]>xs&&y[n]>ys&&dis (x[n],y[n],xs,ys)>t)break ; } for (int i=0 ;i<n;i++){ int tans=0 ,tt=t; if (dis (x[i],y[i],xs,ys)<=tt)tt-=(dis (x[i],y[i],xs,ys)),tans++; else {ans=max (ans,tans);continue ;} for (int j=i;j;j--){ if (dis (x[j],y[j],x[j-1 ],y[j-1 ])<=tt)tt-=(dis (x[j],y[j],x[j-1 ],y[j-1 ])),tans++; else break ; } for (int j=0 ;j<n-1 ;j++){ if (dis (x[j],y[j],x[j+1 ],y[j+1 ])<=tt)tt-=(dis (x[j],y[j],x[j+1 ],y[j+1 ])),tans+=j>=i; else break ; } ans=max (ans,tans); } cout<<ans<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
(2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;void solve () { int n,sl,sh,st=0 ; cin>>n>>sl; int t,l,h; sh=sl; bool flag=0 ; for (int i=1 ;i<=n;i++){ cin>>t>>l>>h; sh=min (h,t-st+sh); sl=max (l,sl-t+st); st=t; if (sl>sh)flag=1 ; } if (flag) cout<<"NO" <<endl; else cout<<"YES" <<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
(3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 131072 ;int ans,num;void bfs (string l,string r,int len,char c) { if (len==0 ){ string zi="" ; zi+=c; if (r==zi){ ans=min (ans,num); }else { ans=min (ans,num+1 ); } return ; } for (int i=0 ;i<len;i++){ if (l[i]!=c){ num++; } } bfs (r.substr (0 ,len/2 ),r.substr (len/2 ,len),len/2 ,(char )(c+1 )); for (int i=0 ;i<len;i++){ if (l[i]!=c){ num--; } } for (int i=0 ;i<len;i++){ if (r[i]!=c){ num++; } } bfs (l.substr (0 ,len/2 ),l.substr (len/2 ,len),len/2 ,(char )(c+1 )); for (int i=0 ;i<len;i++){ if (r[i]!=c){ num--; } } } void solve () { int n; cin>>n; string s; cin>>s; ans=inf,num=0 ; if (n==1 ){ if (s=="a" )cout<<0 <<'\n' ; else cout<<1 <<'\n' ; return ; } string l=s.substr (0 ,n/2 ),r=s.substr (n/2 ,n); bfs (l,r,n/2 ,'a' ); cout<<ans<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
10.排序 希尔排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void shell_sort (int a[],int n) { int gap=n; while (gap>1 ){ gap=gap/3 +1 ; for (int i=1 ;i<=gap;i++){ for (int j=i;j<=n-gap+1 ;j+=gap){ int key=a[j]; int end=j-gap; while (end>=1 &&a[end]>key){ a[end+gap]=a[end]; end-=gap; } a[end+gap]=key; } } } }
归并排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 int arr[N],help[N],n;void merge (int l,int mid,int r) { int i=l,a=l,b=mid+1 ; while (a<=mid&&b<=r){ help[i++]=arr[a]>arr[b]?arr[b++]:arr[a++]; } while (a<=mid){ help[i++]=arr[a++]; } while (b<=r){ help[i++]=arr[b++]; } for (int i=l;i<=r;i++){ arr[i]=help[i]; } } void mergeSort1 (int l,int r) { if (l==r)return ; int mid=(l+r)>>1 ; mergeSort1 (l,mid); mergeSort1 (mid+1 ,r); merge (l,mid,r); } void mergeSort2 (int l,int r) { for (int l,m,r,step=1 ;step<=n;step<<=1 ){ l=0 ; while (l<=n){ m=l+step-1 ; if (m+1 >n)break ; r=min (l+step*2 -1 ,n); merge (l,m,r); l=r+1 ; } } }
快速排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 void quickSort (int l,int r) { if (l>=r)return ; int i=l-1 ,j=r+1 ,x=arr[l+r>>1 ]; while (i<j){ do {i++;}while (arr[i]<x); do {j--;}while (arr[j]>x); if (i<j)swap (arr[i],arr[j]); } quickSort (l,j),quickSort (j+1 ,r); } int first,last;void partition (int l,int r,int x) { first=l,last=r; int i=l; while (i<=last){ if (arr[i]<x){ swap (arr[i++],arr[first++]); }else if (arr[i]==x)i++; else { swap (arr[i],arr[last--]); } } } void quickSort2 (int l,int r) { if (l>=r)return ; int x=arr[l+r>>1 ]; partition (l,r,x); quickSort2 (l,first-1 ); quickSort2 (last+1 ,r); }
计数排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int cnt[N];void countSort (int l,int r) { int Max=arr[l],Min=arr[l]; for (int i=l;i<=r;i++){ if (arr[i]>Max)Max=arr[i]; if (arr[i]<Min)Min=arr[i]; } int len=Max-Min+1 ; for (int i=l;i<=r;i++){ cnt[arr[i]-Min]++; } int it=1 ; for (int i=0 ;i<len;i++){ while (cnt[i]>0 ){ arr[it++]=i+Min; cnt[i]--; } } }
11.0递归 11.01经典递归 //1.返回字符串的所有子序列O(2^n*n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution {public : set<string>st; vector<string>ans; int len; vector<string> generatePermutation (string s) { len=s.length (); solve ("" ,0 ,s); for (auto it:st){ ans.push_back (it); } return ans; } void solve (string s,int i,string ss) { if (i==len){ st.insert (s); return ; } string s1=s; solve (s1,i+1 ,ss); s1=s+ss[i]; solve (s1,i+1 ,ss); return ; } };
//2. O(2^n*n)
//1,1,1,2,2,4,4
//分组:只有0个1的时候,只有1个1的时候,只有2个1的时候,只有3个1的时候(同理只有0个2的时候,只有1个2的时候,只有2个2的时候)
90. 子集 II - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public :vector<vector<int >>ans; vector<vector<int >> subsetsWithDup (vector<int >& nums) { sort (nums.begin (),nums.end ()); vector<int >vec; fun (nums,0 ,vec); return ans; } void fun (vector<int >& nums,int i,vector<int > vec) { if (i==nums.size ()){ ans.push_back (vec); return ; } int j=i+1 ; while (j<nums.size ()&&nums[i]==nums[j])j++; fun (nums,j,vec); for (int t=i;t<j;t++){ vec.push_back (nums[t]); fun (nums,j,vec); } } };
//输出n个数的所有排列(n*n!)
//以原先给定的数组为基准,尝试将每个数交换到i位置,递归下去即可
46. 全排列 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public :vector<vector<int >>ans; vector<vector<int >> permute (vector<int >& nums) { fun (nums,0 ); return ans; } void fun (vector<int >& nums,int i) { if (i==nums.size ()){ vector<int >temp; for (auto it:nums){ temp.push_back (it); } ans.push_back (temp); } for (int j=i;j<nums.size ();j++){ swap (nums[i],nums[j]); fun (nums,i+1 ); swap (nums[i],nums[j]); } } };
//汉罗塔
1 2 3 4 5 6 7 8 void hanluota (int size,char a,char b,char c) { if (size==0 ){ return ; } hanluota (size-1 ,a,c,b); cout<<a<<"->" <<b<<endl; hanluota (size-1 ,c,b,a); }
11.02嵌套类递归
[!IMPORTANT]
定义全局变量where,记录每次嵌套条件结束后i的值,以便后续对i进行更新
结束条件为总问题结结尾或是嵌套问题的结尾
//计算含多层括号的表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int where;void pushFun (deque<int >&numbers,deque<char >&ops,int num,char op) { int size=numbers.size (); if (size==0 ||ops.back ()=='+' ||ops.back ()=='-' ){ numbers.push_back (num); ops.push_back (op); }else { int num1=numbers.back (); char op1=ops.back (); numbers.pop_back (); ops.pop_back (); if (op1=='*' ){ numbers.push_back (num*num1); }else { numbers.push_back (num/num1); } ops.push_back (op); } } int final (deque<int >&numbers,deque<char >&ops) { int ans=numbers.front (); numbers.pop_front (); while (!numbers.empty ()){ ans+=(ops.front ()=='+' ?numbers.front ():-numbers.front ()); numbers.pop_front (); ops.pop_front (); } return ans; } int calculate (string s,int i) { int cur=0 ; deque<int >numbers;deque<char >ops; while (i<s.length ()&&s[i]!=')' ){ if (s[i]>='0' &&s[i]<='9' ){ cur=cur*10 +s[i++]-'0' ; }else if (s[i]!='(' ){ pushFun (numbers,ops,cur,s[i++]); cur=0 ; }else { cur=calculate (s,i+1 ); i=where+1 ; } } pushFun (numbers,ops,cur,'+' ); where=i; return final (numbers,ops); } void solve () { string s; cin>>s; cout<<calculate (s,0 )<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
11.动态规划 983. 最低票价 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution {public : const int inf=0x3f3f3f3f ; int duration[3 ]={1 ,7 ,30 },dp[366 ]={0 }; int mincostTickets (vector<int >& days, vector<int >& costs) { return solve (days,costs,0 ); } int solve (vector<int >& days,vector<int >& costs,int i) { if (i==days.size ())return 0 ; if (dp[i])return dp[i]; int ans=inf; for (int k=0 ,j=i;k<3 ;k++){ while (j<days.size ()&&days[i]+duration[k]>days[j])j++; ans=min (ans,costs[k]+solve (days,costs,j)); } dp[i]=ans; return ans; } }; class Solution {public : const int inf=0x3f3f3f3f ; int duration[3 ]={1 ,7 ,30 },dp[366 ]; int mincostTickets (vector<int >& days, vector<int >& costs) { return solve (days,costs,days.size ()); } int solve (vector<int >& days,vector<int >& costs,int n) { for (int i=0 ;i<366 ;i++){ dp[i]=inf; } int ans=inf; dp[n]=0 ; for (int i=n-1 ;i>=0 ;i--){ for (int k=0 ,j=i;k<3 ;k++){ while (j<n&&days[i]+duration[k]>days[j])j++; dp[i]=min (dp[i],costs[k]+dp[j]); } } return dp[0 ]; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 class Solution {public : int dp[105 ]; int numDecodings (string s) { return solve (s,0 ); } int solve (string s,int i) { if (i==s.length ())return 1 ; if (dp[i])return dp[i]; int ans=0 ; if (s[i]=='0' ){ ans=0 ; }else { ans=solve (s,i+1 ); if (i+1 <s.length ()&&(s[i]-'0' )*10 +s[i+1 ]-'0' <=26 ){ ans+=solve (s,i+2 ); } } dp[i]=ans; return ans; } }; class Solution {public : int dp[105 ]; int numDecodings (string s) { return solve (s,0 ); } int solve (string s,int i) { dp[s.length ()]=1 ; for (int i=s.length ()-1 ;i>=0 ;i--){ if (s[i]=='0' ){ dp[i]=0 ; }else { dp[i]=dp[i+1 ]; if (i+1 <s.length ()&&(s[i]-'0' )*10 +s[i+1 ]-'0' <=26 ){ dp[i]+=dp[i+2 ]; } } } return dp[0 ]; } }; class Solution {public : int numDecodings (string s) { return solve (s,0 ); } int solve (string s,int i) { int n=1 ,nn=0 ,cnt; for (int i=s.length ()-1 ;i>=0 ;i--){ if (s[i]=='0' ){ cnt=0 ; nn=n; n=cnt; }else { cnt=n; if (i+1 <s.length ()&&(s[i]-'0' )*10 +s[i+1 ]-'0' <=26 ){ cnt+=nn; } nn=n; n=cnt; } } return n; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 class Solution {public :const long mod=1e9 +7 ;long dp[100005 ]; int numDecodings (string s) { return (int )fun (s); } long fun (string s) { int n=s.length (); dp[n]=1 ; for (int i=n-1 ;i>=0 ;i--){ if (s[i]=='0' )continue ; dp[i]=dp[i+1 ]*(s[i]=='*' ?9 :1 ); if (i+1 <n){ if (s[i]!='*' ){ if (s[i+1 ]!='*' ){ if (((s[i]-'0' )*10 +s[i+1 ]-'0' )<=26 ){ dp[i]+=dp[i+2 ]; } }else { if (s[i]=='1' ){ dp[i]+=dp[i+2 ]*9 ; }else if (s[i]=='2' ){ dp[i]+=dp[i+2 ]*6 ; } } }else { if (s[i+1 ]!='*' ){ if (s[i+1 ]<='6' )dp[i]+=dp[i+2 ]*2 ; else dp[i]+=dp[i+2 ]; }else { dp[i]+=dp[i+2 ]*15 ; } } } dp[i]=dp[i]%mod; } return dp[0 ]; } }; class Solution {public :const long mod=1e9 +7 ; int numDecodings (string s) { return (int )fun (s); } long fun (string s) { int len=s.length (); long nn=0 ,n=1 ,cur; for (int i=len-1 ;i>=0 ;i--){ if (s[i]=='0' ){ cur=0 ; nn=n; n=cur; continue ; } cur=n*(s[i]=='*' ?9 :1 ); if (i+1 <len){ if (s[i]!='*' ){ if (s[i+1 ]!='*' ){ if (((s[i]-'0' )*10 +s[i+1 ]-'0' )<=26 ){ cur+=nn; } }else { if (s[i]=='1' ){ cur+=nn*9 ; }else if (s[i]=='2' ){ cur+=nn*6 ; } } }else { if (s[i+1 ]!='*' ){ if (s[i+1 ]<='6' )cur+=nn*2 ; else cur+=nn; }else { cur+=nn*15 ; } } } cur=cur%mod; nn=n; n=cur; } return n; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : int dp[3 *10000 +5 ]; int longestValidParentheses (string s) { s=" " +s; int n=s.length (); for (int i=1 ;i<n;i++){ if (s[i]==')' ){ int j=i-1 -dp[i-1 ]; if (s[j]=='(' ){ dp[i]=dp[i-1 ]+2 +dp[j-1 ]; } } } int ans=0 ; for (int i=1 ;i<n;i++){ ans=max (ans,dp[i]); } return ans; } };
1274: D003 Help Jimmy P1274 - D003 Help Jimmy - NENUOJ
Min(i,true)表示从第i块板子的左侧出发到地面的最短距离
minleft[i]用来记录从第i块板子的左侧出发到地面的最短距离
minright[i]用来记录从第i块板子的右侧出发到地面的最短距离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e3 + 5 ;int minleft[N];int minright[N],Max,n;struct node { int x1,x2,h; }arr[N]; bool cmp (node a,node b) { return a.h>b.h; } int Min (int k,bool left) { int x,y=arr[k].h,i; if (left){ x=arr[k].x1; }else { x=arr[k].x2; } for (i=k+1 ;i<=n;i++){ if (arr[i].x1<=x&&arr[i].x2>=x){ break ; } } if (i==(n+1 )){ if (y>Max)return inf; else return y; } else { if (y-arr[i].h>Max)return inf; } int lefttime=y-arr[i].h+x-arr[i].x1,righttime=y-arr[i].h+arr[i].x2-x; if (minleft[i]==-1 ){ minleft[i]=Min (i,true ); } if (minright[i]==-1 ){ minright[i]=Min (i,false ); } return min (minleft[i]+lefttime,minright[i]+righttime); } void solve () { int x,y; cin>>n>>x>>y>>Max; arr[0 ].x1=x,arr[0 ].x2=x,arr[0 ].h=y; for (int i=0 ;i<=n;i++){ minleft[i]=-1 ; minright[i]=-1 ; } for (int i=1 ;i<=n;i++){ cin>>arr[i].x1>>arr[i].x2>>arr[i].h; } sort (arr+1 ,arr+1 +n,cmp); cout<<Min (0 ,true )<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
1275: D004 最长公共子序列 //动态规划的重要思想就是将整体问题划分为子问题
当s1的第i个字母与s2的第j个字母一样时,我们原本要求的s1中的前i个字母和s2中的前j个字母/有多少个最长公共子序列的问题(即求dp/[i]/[j])便转化为了求dp/[i-1]/[j-1]
当它们不一样时,我们便可在dp/[i-1]/[j]和dp/[i]/[j-1]中取最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 2e2 + 5 ;int dp[N][N];string s1,s2; void solve () { while (cin>>s1>>s2){ s1=" " +s1; s2=" " +s2; int len1=s1.l ength(); int len2=s2.l ength(); memset (dp, 0 , sizeof (dp)); for (int i=1 ;i<len1;i++){ for (int j=1 ;j<len2;j++){ if (s1[i]==s2[j]){ dp[i][j] = dp[i-1 ][j-1 ] + 1 ; }else { dp[i][j] = max (dp[i-1 ][j], dp[i][j-1 ]); } } } cout<<dp[len1-1 ][len2-1 ]<<endl; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
12.差分 等差数列差分
[!NOTE]
1 在arr[l]+=s,arr[l+1 ]+=(d-s),arr[r+1 ]-=(d+e),arr[r+2 ]+=e;
两轮叠加:
第一轮s d d d d d d -e 0 0
第二轮s s+d s+2d s+3d s+4d s+5d s+6d 0 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ,OFFSET=30005 ;int arr[N+OFFSET*2 ];void setArr (int l,int r,int s,int d,int e) { arr[l+OFFSET]+=s; arr[l+1 +OFFSET]+=d-s; arr[r+1 +OFFSET]-=(e+d); arr[r+2 +OFFSET]+=e; } void solve () { int n,m; cin>>n>>m; while (n--){ int v,x; cin>>v>>x; setArr (x-3 *v+1 ,x-2 *v,1 ,1 ,v); setArr (x-2 *v+1 ,x,v-1 ,-1 ,-v); setArr (x+1 ,x+2 *v,-v+1 ,1 ,v); setArr (x+2 *v+1 ,x+3 *v,v-1 ,-1 ,0 ); } for (int i=1 ;i<=m+OFFSET;i++){ arr[i]+=arr[i-1 ]; } for (int i=1 ;i<=m+OFFSET;i++){ arr[i]+=arr[i-1 ]; } for (int i=1 +OFFSET;i<=m+OFFSET;i++){ cout<<arr[i]<<' ' ; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
问题: 1 2 3 4 5 6 7 8 9 while (n--){ int v,x; cin>>v>>x; setArr (x-3 *v,x-2 *v,0 ,1 ,v); setArr (x-2 *v,x,v,-1 ,-v); setArr (x,x+2 *v,-v,1 ,v); setArr (x+2 *v,x+3 *v,v,-1 ,0 ); }
13.堆结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void heapInsert (int i) { while (arr[i]>arr[(i-1 )/2 ]){ swap (arr[i],arr[(i-1 )/2 ]); i=(i-1 )/2 ; } } void heapify (int i,int size) { int l=2 *i+1 ; while (l<size){ int best=(l+1 <size&&arr[l+1 ]>arr[l])?(l+1 ):l; best=arr[i]>arr[best]?i:best; if (best==i)break ; swap (arr[i],arr[best]); i=best; l=2 *i+1 ; } }
堆排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void heapInsert (int i) { while (arr[i]>arr[(i-1 )/2 ]){ swap (arr[i],arr[(i-1 )/2 ]); i=(i-1 )/2 ; } } void heapify (int i,int size) { int l=2 *i+1 ; while (l<size){ int best=(l+1 <size&&arr[l+1 ]>arr[l])?(l+1 ):l; best=arr[i]>arr[best]?i:best; if (best==i)break ; swap (arr[i],arr[best]); i=best; l=2 *i+1 ; } } void heapSort () { int n=10 ; for (int i=0 ;i<n;i++){ heapInsert (i); } int size=n; while (size>1 ){ swap (arr[0 ],arr[--size]); heapify (0 ,size); } }
14.二叉树 1.二叉树的层序遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Solution {public :TreeNode* q[2100 ]; vector<int >arr; vector<vector<int >> levelOrder (TreeNode* root) { vector<vector<int >> ans; if (root!=nullptr ){ int l=0 ,r=0 ; q[r++]=root; while (l<r){ int size=r-l; while (size--){ TreeNode* x=q[l++]; if (x==nullptr )continue ; arr.push_back ((x->val)); if (x->left!=nullptr ){ q[r++]=x->left; } if (x->right!=nullptr ){ q[r++]=x->right; } } ans.push_back (arr); arr.clear (); } } return ans; } };
2.二叉树的锯齿形层序遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Solution {public :TreeNode* q[2005 ]; vector<int >arr; vector<vector<int >> zigzagLevelOrder (TreeNode* root) { vector<vector<int >>ans; if (root!=nullptr ){ int l=0 ,r=0 ; q[r++]=root; bool flag=false ; while (l<r){ int size=r-l,i; if (flag==false )i=l; else i=r-1 ; for (int k=1 ;k<=size;k++){ if (q[i]==nullptr )continue ; arr.push_back (q[i]->val); if (flag)i--; else i++; } while (size--){ TreeNode* x=q[l++]; if (x==nullptr )continue ; if (x->left!=nullptr ){ q[r++]=x->left; } if (x->right!=nullptr ){ q[r++]=x->right; } } ans.push_back (arr); flag=!flag; arr.clear (); } } return ans; } };
3.二叉树的最大宽度 662. 二叉树最大宽度 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Solution {public :TreeNode* nq[3005 ]; unsigned long long q[3005 ]; int widthOfBinaryTree (TreeNode* root) { unsigned long long ans=0 ; if (root==nullptr )return ans; unsigned long long l=0 ,r=0 ; nq[r]=root; q[r++]=1 ; while (l<r){ unsigned long long size=r-l; ans=max (ans,q[r-1 ]-q[l]+1 ); while (size--){ TreeNode* x=nq[l]; unsigned long long iq=q[l++]; if (x==nullptr )continue ; if (x->left!=nullptr ){ nq[r]=x->left; q[r++]=iq*2 ; } if (x->right!=nullptr ){ nq[r]=x->right; q[r++]=iq*2 +1 ; } } } return (int )ans; } };
4.二叉树的最大深度 104. 二叉树的最大深度 - 力扣(LeetCode)
1 2 3 int maxDepth (TreeNode* root) { return (root==nullptr ?0 :max (maxSolve (root->left),maxSolve (root->right))+1 ); }
5.二叉树的最小深度 111. 二叉树的最小深度 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 int minDepth (TreeNode* root) { if (root==nullptr )return 0 ; if (root->left==nullptr &&root->right==nullptr )return 1 ; int leftDepth=inf,rightDepth=inf; if (root->left!=nullptr ){ leftDepth=minDepth (root->left); } if (root->right!=nullptr ){ rightDepth=minDepth (root->right); } return min (leftDepth,rightDepth)+1 ; }
6.知前中序遍历求后序 1 2 3 4 5 6 7 8 9 10 11 12 13 void tree (string front,string mid) { if (front.empty ())return ; char root=front[0 ]; int k=mid.find (root); front.erase (front.begin ()); string leftfront=front.substr (0 ,k); string rightfront=front.substr (k); string leftmid=mid.substr (0 ,k); string rightmid=mid.substr (k+1 ); tree (leftfront,leftmid); tree (rightfront,rightmid); cout<<root; }
7.知后中序遍历写前序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void work (string mid,string back) { if (back.empty ())return ; char root=back[back.size ()-1 ]; int k=mid.find (root); back.erase (back.end ()-1 ); string leftmid=mid.substr (0 ,k); string rightmid=mid.substr (k+1 ); string leftback=back.substr (0 ,k); string rightback=back.substr (k); cout<<root; work (leftmid,leftback); work (rightmid,rightback); }
8.计算二叉树的节点个数 222. 完全二叉树的节点个数 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution {public : int countNodes (TreeNode* root) { if (root==nullptr )return 0 ; return f (root,1 ,findDepth (root,1 )); } int f (TreeNode* root,int level,int h) { if (level==h)return 1 ; if (findDepth (root->right,level+1 )==h){ return (1 <<(h-level))+f (root->right,level+1 ,h); }else { return (1 <<(h-level-1 ))+f (root->left,level+1 ,h); } } int findDepth (TreeNode* root,int level) { while (root){ level++; root=root->left; } return level-1 ; } };
9.二叉树的最近公共祖先 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : TreeNode* lowestCommonAncestor (TreeNode* root, TreeNode* p, TreeNode* q) { if (root==nullptr ||root==p||root==q)return root; TreeNode* l=lowestCommonAncestor (root->left,p,q); TreeNode* r=lowestCommonAncestor (root->right,p,q); if (l!=nullptr &&r!=nullptr ){ return root; } if (l==nullptr &&r==nullptr ){ return nullptr ; } return l==nullptr ?r:l; } }; TreeNode* solve (TreeNode* root ,TreeNode* p,TreeNode* q) { while (root!=p&&root!=q){ if (min (p->val,q->val)<root->val&&max (p->val,q->val)>root->val){ break ; } root=root->val<min (p->val,q->val)?root->right:root->left; } return root; }
10.路径总和 113. 路径总和 II - 力扣(LeetCode)
//注意回溯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Solution {public :vector<vector<int >>ans; deque<int >q; vector<vector<int >> pathSum (TreeNode* root, int targetSum) { if (root==nullptr )return ans; solve (root,targetSum,0 ); return ans; } void solve (TreeNode* root,int targetSum,int curSum) { if (root->left==nullptr &&root->right==nullptr ){ if (root->val+curSum==targetSum){ q.push_back (root->val); copy (); q.pop_back (); } }else { q.push_back (root->val); if (root->left!=nullptr ){ solve (root->left,targetSum,curSum+root->val); } if (root->right!=nullptr ){ solve (root->right,targetSum,curSum+root->val); } q.pop_back (); } } void copy () { vector<int >arr; for (auto it:q){ arr.push_back (it); } ans.push_back (arr); } };
11.验证平衡二叉树 //flag的重要性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution {public :bool ans; bool isBalanced (TreeNode* root) { ans=true ; height (root); return ans; } int height (TreeNode* root) { if (!ans||root==nullptr ){ return 0 ; } int lh=height (root->left); int rh=height (root->right); if (abs (lh-rh)>1 ){ ans=false ; } return max (lh,rh)+1 ; } };
12.验证二叉搜索树(涉及中序遍历的非递归实现) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 class Solution {public : bool isValidBST (TreeNode* root) { if (root==nullptr )return true ; stack<TreeNode*>st; TreeNode* pre=nullptr ; while (!st.empty ()||root!=nullptr ){ if (root!=nullptr ){ st.push (root); root=root->left; }else { root=st.top (); st.pop (); if (pre!=nullptr &&pre->val>=root->val){ return false ; } pre=root; root=root->right; } } return true ; } }; class Solution {public :long long Max,Min;const long long MMAX=3000000000 ,MMIN=-3000000000 ; bool isValidBST (TreeNode* root) { if (root==nullptr ){ Max=MMIN; Min=MMAX; return true ; } bool lok=isValidBST (root->left); long long lmax=Max; long long lmin=Min; bool rok=isValidBST (root->right); long long rmax=Max; long long rmin=Min; Max=max (max (lmax,rmax),(long long )(root->val)); Min=min (min (lmin,rmin),(long long )(root->val)); return lok&&rok&&(lmax<(long long )(root->val))&&((long long )(root->val)<rmin); } };
13.修剪搜索二叉树(递归) 669. 修剪二叉搜索树 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution {public : TreeNode* trimBST (TreeNode* root, int low, int high) { if (root==nullptr )return nullptr ; if (root->val<low){ return trimBST (root->right,low,high); } if (root->val>high){ return trimBST (root->left,low,high); } root->left=trimBST (root->left,low,high); root->right=trimBST (root->right,low,high); return root; } };
14.打家劫舍iii 337. 打家劫舍 III - 力扣(LeetCode)
//yes代表偷子节点,no代表不投子节点
//y代表偷当前子节点,n代表不投当前子节点
//很像dp了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public :int yes,no; int rob (TreeNode* root) { f (root); return max (yes,no); } void f (TreeNode* root) { if (root==nullptr ){ yes=0 ; no=0 ; }else { int y=root->val; int n=0 ; f (root->left); y+=no; n+=max (yes,no); f (root->right); y+=no; n+=max (yes,no); yes=y; no=n; } } };
15.树状数组
应用:(可求逆序对数)
每个下标a管的范围:其二进制最右侧的1变为0,然后加1,变为b
[b,a];
//[前缀树状数组]单点增加,范围查询(前缀) //t[i]代表具有一定规律的某一范围的和
1 2 3 4 5 6 7 8 9 10 11 12 int lowbit (int x) { return x & -x; } void update (int k, int x) { for (int i = k; i <= n; i += lowbit(i)) t[i] += x; } int getprefix (int k) { int res = 0 ; for (int i = k; i > 0 ; i -= lowbit(i)) res += t[i]; return res; }
1. [P1966 NOIP 2013 提高组] 火柴排队 - 洛谷
第一次错是因为结果忘记取模
//疑问如果高度有相同的会不会影响结果,样例是没有这部分测试的或许
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ,mod=1e8 -3 ;struct node { int val,id; } a[N],b[N]; bool cmp (node x,node y) { return x.val<y.val; } int c1[N];int c2[N];int c3[N];int t[N],n;int lowbit (int x) { return x&(-x); } void update (int x,int y) { for (int i=x;i<=n;i+=lowbit (i)){ t[i]+=y; } } int query (int x) { int res = 0 ; for (int i=x;i>0 ;i-=lowbit (i)){ res=(res%mod+t[i]%mod)%mod; } return res; } void solve () { cin>>n; for (int i=1 ;i<=n;i++){ cin>>a[i].val; a[i].id=i; } for (int i=1 ;i<=n;i++){ cin>>b[i].val; b[i].id=i; } sort (a+1 ,a+n+1 ,cmp); sort (b+1 ,b+n+1 ,cmp); for (int i=1 ;i<=n;i++){ c1[a[i].id]=i; c2[b[i].id]=i; } for (int i=1 ;i<=n;i++){ c3[c2[i]]=i; } for (int i=1 ;i<=n;i++){ c2[i]=c3[c1[i]]; } int res=0 ; for (int i=1 ;i<=n;i++){ update (c2[i],1 ); res=((res%mod+query (n)%mod)%mod+(-query (c2[i])%mod+mod)%mod)%mod; } cout<<res<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
//[差分树状数组]范围增加,单点查询,利用差分数组(差分) //t[i]代表某一范围的差分和
//求和可得某一位置的数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int n,t[N],arr[N];int lowbit (int x) { return x&(-x); } void update (int x,int val) { for (int i=x;i<=n;i+=lowbit (i))t[i]+=val; } int query (int x) { int ans=0 ; for (int i=x;i>0 ;i-=lowbit (i))ans+=t[i]; return ans; } void solve () { int m; cin>>n>>m; for (int i=1 ;i<=n;i++){ cin>>arr[i]; } for (int i=1 ;i<=n;i++){ update (i,arr[i]-arr[i-1 ]); } while (m--){ int op,x,y,k; cin>>op; if (op==1 ){ cin>>x>>y>>k; update (x,k); update (y+1 ,-k); } else { cin>>x; cout<<query (x)<<endl; } } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
//范围增加,范围查询 线段树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 void build (int s, int t, int p) { if (s == t) { d[p] = a[s]; return ; } int m = s + ((t - s) >> 1 ); build(s, m, p * 2 ), build(m + 1 , t, p * 2 + 1 ); d[p] = d[p * 2 ] + d[(p * 2 ) + 1 ]; } void pushdown (int s, int e, int o) { if (lz[o]) { int mid = (s + e) / 2 ; t[o * 2 ] += (mid - s + 1 ) * lz[o]; t[o * 2 + 1 ] += (e - mid) * lz[o]; lz[o * 2 ] += lz[o]; lz[o * 2 + 1 ] += lz[o]; lz[o] = 0 ; } } void update (int l, int r, int v, int s, int e, int o) { if (l <= s && r >= e) { t[o] += (e - s + 1 ) * v; lz[o] += v; return ; } pushdown(s, e, o); int mid = (s + e) / 2 ; if (l <= mid) update(l, r, v, s, mid, o * 2 ); if (r > mid) update(l, r, v, mid + 1 , e, o * 2 + 1 ); pushup(o); } int getsum (int l, int r, int s, int t, int p) { if (l <= s && t <= r) return d[p]; pushdown(s,t,p); int m = s + ((t - s) >> 1 ), sum = 0 ; if (l <= m) sum += getsum(l, r, s, m, p * 2 ); if (r > m) sum += getsum(l, r, m + 1 , t, p * 2 + 1 ); return sum; }
可持久化线段树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void build (int & x, int l, int r) { x = ++idx; if (l == r)return ; int mid = (l + r) >> 1 ; build (lc (x), l, mid); build (rc (x), mid + 1 , r); } void update (int pre, int & o, int l, int r, int v) { o = ++idx; t[o] = t[pre]; t[o].val++; if (l == r)return ; int mid = (l + r) >> 1 ; if (v <= mid) update (lc (pre), lc (o), l, mid, v); else update (rc (pre), rc (o), mid + 1 , r, v); } int query (int x, int y, int l, int r, int k) { if (l == r)return l; int mid = (l + r) >> 1 ; int s = t[lc (y)].val - t[lc (x)].val; if (k <= s) return query (lc (x), lc (y), l, mid, k); else return query (rc (x), rc (y), mid + 1 , r, k - s); }
欧拉筛 如果能让每个合数都只被标记一次,那么时间复杂度就可以降到 𝑂(𝑛)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void euler (int n) { vector<int > primes; bool vis[n + 1 ] = {false }; vis[0 ] = vis[1 ] = true ; for (int i = 2 ; i <= n; ++i) { if (!vis[i]) { primes.push_back (i); } for (int j = 0 ; j < primes.size () && i * primes[j] <= n; ++j) { vis[i * primes[j]] = true ; if (i % primes[j] == 0 ) { break ; } } } }
Kruskal算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 struct Edge { int x, y, c; bool operator < (const Edge &u) const { return c < u.c; } }; int pre[N];int root (int x) { return pre[x] == x ? x : root (pre[x]); } void solve () { int n, m; cin >> n >> m; vector<Edge> es; for (int i = 1 ; i <= m; ++ i) { int x, y, c; cin >> x >> y >> c; es.push_back ({x, y, c}); } sort (es.begin (), es.end ()); for (int i = 1 ; i <= n; ++ i) pre[i] = i; int ans = 0 ; for (const auto & [x, y, c] : es) { if (root (x) == root (y)) continue ; ans = max (ans, c); pre[root (x)] = root (y); } cout << ans << '\n' ; }
Prim算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 struct Edge { ll x, c; bool operator < (const Edge &u) const { return c == u.c ? x > u.x : c < u.c; } }; vector<Edge> g[N]; ll d[N]; int n, m;int prim () { priority_queue<Edge> pq; bitset<N> vis; d[1 ] = 0 ; pq.push ({1 , d[1 ]}); ll res = 0 ; while (pq.size ()) { int x = pq.top ().x; pq.pop (); if (vis[x]) continue ; vis[x] = true ; res = max (res, d[x]); for (const auto &[y, w] : g[x]) { if (!vis[y]) { d[y] = min (d[y], w); pq.push ({y, d[y]}); } } } return res; }
16.链表
[!NOTE]
写链表的题是要特别注意非空判断,避免空指针异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;struct ListNode { int val; ListNode *next; ListNode () : val (0 ), next (nullptr ) {} ListNode (int x) : val (x), next (nullptr ) {} ListNode (int x, ListNode *next) : val (x), next (next) {} }; void solve () { int n,m; cin>>n>>m; ListNode* head=new ListNode (1 ); ListNode* p=head; for (int i=2 ;i<=n;i++){ p->next=new ListNode (i); p=p->next; } p->next=head; int num=n; p=head; ListNode* pre=p; while (num){ for (int i=1 ;i<=m-1 &&p!=nullptr ;i++){ pre=p; p=p->next; } if (p==nullptr ) break ; cout<<p->val<<" " ; pre->next=p->next; delete p; p=pre->next; num--; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
//双重循环会超时(1e5*1e5),但一般看到这个我们还会想到一种方法,那就是对应数值索引
//这道题的思路很简单,就是的注意非空判断,以及更改的先后顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ;struct ListNode { int val; ListNode *next,*pre; ListNode ():val (0 ),next (nullptr ){} ListNode (int x):val (x),next (nullptr ){} }arr[N]; void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++){ arr[i].val=i; } for (int i=2 ;i<=n;i++){ int k,p; cin>>k>>p; if (p==1 ){ arr[i].next=arr[k].next; if (arr[k].next!=nullptr )arr[k].next->pre=&(arr[i]); arr[k].next=&(arr[i]); arr[i].pre=&(arr[k]); }else { arr[i].pre=arr[k].pre; if (arr[k].pre!=nullptr )arr[k].pre->next=&(arr[i]); arr[i].next=&(arr[k]); arr[k].pre=&(arr[i]); } } int m; cin>>m; while (m--){ int x; cin>>x; if (arr[x].val==0 )continue ; arr[x].val=0 ; if (arr[x].pre!=nullptr )arr[x].pre->next=arr[x].next; if (arr[x].next!=nullptr )arr[x].next->pre=arr[x].pre; arr[x].pre=nullptr ; arr[x].next=nullptr ; } int mark=0 ; for (int i=1 ;i<=n;i++){ if (arr[i].pre==nullptr &&arr[i].next!=nullptr ){ mark=i; break ; } } ListNode *head=&(arr[mark]); while (head){ cout<<head->val<<" " ; head=head->next; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
17.打表 构造题就打表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int n;int vis[N];deque<int >ans; int cnt;void dfs (int dep,int sum) { if (dep==n&&cnt==0 ){ cnt++; for (auto x:ans){ cout<<x<<" " ; } cout<<endl; return ; } for (int i=0 ;i<=n-1 ;i++){ if (vis[i])continue ; if (!(sum^i))continue ; vis[i]=1 ; ans.push_back (i); dfs (dep+1 ,sum^i); vis[i]=0 ; ans.pop_back (); } } void solve () { cnt=0 ; cin>>n; dfs (0 ,0 ); } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 //https://codeforces.com/gym/105386/problem/G #include <bits/stdc++.h> using namespace std; #define int long long const int inf=0x3f3f3f3f,N = 1e6 + 5; int a[N]; void solve(){ int n; cin>>n; if(n%4==0||n==1){ cout<<"impossible\n"; return ; } if(n==2){ cout<<"1 0\n"; return; } if(n==3){ cout<<"1 0 2\n"; return ; } a[0]=1; a[1]=0; a[2]=2; for(int i=3;i<n;i++){ a[i]=i; if(i%4==0){ swap(a[i-1],a[i]); } } for(int i=0;i<n;i++){ cout<<a[i]<<' '; } cout<<'\n'; } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t=1; cin>>t; while(t--){ solve(); } return 0; }
18.唯一分解定理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 for (int i = 2 ; i <= x / i; ++i) { if (x % i) continue ; int cnt = 0 ; while (x % i == 0 ) cnt++, x /= i; v.push_back ({i, cnt}); } if (x > 1 ) v.push_back ({x, 1 }); for (const auto & i : v) cout << i.first << ' ' << i.second << '\n' ; 因数个数的寻找与一些数学谜题息息相关。现在小编为大家分享一下自我研究出的通过分解质因数寻找因数个数的方法。 首先讲一个数分解质因数,如果有相同的质因数就整理成幂次方的形式。将结果的指数加一,再将此结果相乘得到其因数个数。 举例:72 ,用列举法不易找出其因数个数。而72 =2 ×2 ×2 ×3 ×3 =2 ³×3 ²,分别将指数3 ,2 加一变成4 ,3 ,4 ×3 =12 个。列举证明1 ,2 ,3 ,4 ,6 ,8 ,9 ,12 ,18 ,24 ,36 ,72 共12 个因数。
19.搜索 [P1219 USACO1.5] 八皇后 Checker Challenge - 洛谷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int arr[15 ][15 ],brr[15 ][15 ],n,ans;deque<int >st; bool check () { for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ brr[i][j]=arr[i][j]; } } for (int i=1 ;i<=n;i++){ int sum=0 ; for (int j=1 ;j<=n;j++){ sum+=brr[j][i]; } if (sum!=1 )return false ; } for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ if (brr[i][j]==1 ){ if (i+1 >n||j+1 >n){continue ;} if (brr[i+1 ][j+1 ]==1 ){ return false ; } brr[i+1 ][j+1 ]=1 ; } } } for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ brr[i][j]=arr[i][j]; } } for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ if (brr[i][j]==1 ){ if (i+1 >n||j-1 <1 ){continue ;} if (brr[i+1 ][j-1 ]==1 ){ return false ; } brr[i+1 ][j-1 ]=1 ; } } } return true ; } void dfs (int x, int y) { if (x==n){ if (check ()){ ans++; if (ans>3 )return ; for (auto it:st){ cout<<it<<" " ; } cout<<'\n' ; } return ; } for (int i=1 ;i<=n;i++){ arr[x+1 ][i]=1 ; st.push_back (i); dfs (x+1 ,i); arr[x+1 ][i]=0 ; st.pop_back (); } } void solve () { cin>>n; for (int i=1 ;i<=n;i++){ arr[1 ][i]=1 ; st.push_back (i); dfs (1 ,i); arr[1 ][i]=0 ; st.pop_back (); } cout<<ans<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
直接用vis1和vis2对斜对角线上的元素是否有重叠进行标记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <bits/stdc++.h> using namespace std; #define int long long const int inf=0x3f3f3f3f,N = 1e6 + 5; int arr[15][15],brr[15][15],n,ans; deque<int>st; int vis[15],vis1[35],vis2[35]; void dfs(int x, int y){ if(x==n){ ans++; if(ans>3)return ; for(auto it:st){ cout<<it<<" "; } cout<<'\n'; return ; } for(int i=1;i<=n;i++){ if(vis[i]){continue;} if(vis1[i-(x+1)+n]){continue;} if(vis2[i+x+1]){continue;} arr[x+1][i]=1; vis[i]=1; vis1[i-(x+1)+n]=1; vis2[i+x+1]=1; st.push_back(i); dfs(x+1,i); arr[x+1][i]=0; vis[i]=0; st.pop_back(); vis1[i-(x+1)+n]=0; vis2[i+x+1]=0; } } void solve(){ cin>>n; for(int i=1;i<=n;i++){ arr[1][i]=1; vis[i]=1; st.push_back(i); vis1[i-1+n]=1; vis2[i+1]=1; dfs(1,i); arr[1][i]=0; st.pop_back(); vis[i]=0; vis1[i-1+n]=0; vis2[i+1]=0; } cout<<ans<<'\n'; } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t=1; // cin>>t; while(t--){ solve(); } return 0; }
math 位运算 打表找规律
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;vector<string> digui (int n) { if (n==1 ){ vector<string>ans; ans.push_back ("0" ); ans.push_back ("1" ); return ans; } vector<string>temp; temp=digui (n-1 ); vector<string>res; for (int i=0 ;i<temp.size ();i++){ res.push_back ("0" +temp[i]); } for (int i=temp.size ()-1 ;i>=0 ;i--){ res.push_back ("1" +temp[i]); } return res; } void solve () { int n; cin>>n; vector<string>ans=digui (n); for (int i=0 ;i<ans.size ();i++){ cout<<ans[i]<<' ' ; } cout<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; cin>>t; while (t--){ solve (); } return 0 ; }
这道题很明显是有蹊跷的,数据范围过大。
但是让我找规律我未必能发现
但仔细思考一下,位数高达64位,我们不可能生成所有数再查询,所以只可能是每一个数的每位是0还是1有规律可寻,所以我们自然而然的去关注打表后每一个数的每一位是否呈现某种规律
规律:
倒数第n位就是 2^(n −1) 个 0 , 2^(n −1) 个 1 , 2^(n −1) 个 1 , 2^(n −1) 个 0 循环
位数高达64,得用unsigned long long
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <bits/stdc++.h> using namespace std;#define int unsigned long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int ans[64 ];int num[]={0 ,1 ,1 ,0 };void solve () { int n,k; cin>>n>>k; for (int i=n-1 ;i>0 ;i--){ cout<<num[(k/((int )(1 )<<i))%4 ]; } cout<<num[k%4 ]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
第k个格雷码=k^(k>>1)
我们再输出每一位即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <bits/stdc++.h> using namespace std;#define int unsigned long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int num[]={0 ,1 ,1 ,0 };void solve () { int n,k; cin>>n>>k; k=k^(k>>1 ); while (n){ n--; if (k==-1 ) break ; cout<<((k>>n)&1 ); } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
a最大可达1e9则我们设置a的二进制最大有32位,统计每一个a的每一位是否为1,
cnt[i]代表i位为1的a的个数,若该位的1为奇数个,则无论如何组合该位都会留下,其他位同理,我们最后只需对留下的1乘以他们所对应的位权即可
从以上推出更简单的结果所得公式ans=0;ans^=a;cout<<ans;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;int cnt[35 ];void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++){ int a; cin>>a; for (int j=31 ;j>=0 ;j--){ cnt[j]+=((a>>j)&1 ); } } int ans=0 ; for (int i=31 ;i>=0 ;i--){ if (cnt[i]%2 ==1 ) ans+=(1 <<i); } cout<<ans<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
题目要求的是把 S 集合中所有的数的倍数标记之后,连续 3 个都被标记的位置的数量(这步采用位运算,非常巧妙。)
bs 数组 :用二进制位标记数字是否被选中。unsigned long long 是 64 位,因此 bs[k] 对应数字 k*64 ~ (k+1)*64-1,其中第 b 位(0≤b<64)为 1 表示数字 k*64 + b 被标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> #define N 1000000003 #define reg register using namespace std;unsigned long long bs[(N>>6 )+10 ];unsigned long long tmp[65 ];int n,m,s,l,ans;inline int count (unsigned long long x) { reg int res = 0 ; while (x){ res += x&1 ; x >>= 1 ; } return res; } int main () { cin>>n>>s; m = (n>>6 )+1 ; while (s--){ cin>>l; if (l<64 ){ memset (tmp,0 ,sizeof (tmp)); for (reg int i=0 ;i<(l<<6 );i+=l) tmp[i>>6 ] |= 1ull <<(i&63 ); for (reg int i=0 ;i<=m;i+=l) for (reg int j=0 ;j<l;++j) bs[i+j] |= tmp[j]; }else { for (reg int i=0 ;i<=n;i+=l) bs[i>>6 ] |= 1ull <<(i&63 ); } } --m; if ((n&63 )!=63 ) bs[m] &= (1ull <<(n+1 -(m<<6 )))-1 ; bs[0 ] &= -2ull ; for (reg int i=0 ;i<=m;++i) ans += count (bs[i]&(bs[i]<<1 )&(bs[i]<<2 )); for (reg int i=1 ;i<=m;++i) ans += count (bs[i]&(bs[i-1 ]>>62 )&((bs[i-1 ]>>63 )|(bs[i]<<1 ))); cout<<ans; return 0 ; }
素数 Miller Rabin(高精度素数判定) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 bool millerRabin (int n) { if (n < 3 || n % 2 == 0 ) return n == 2 ; if (n % 3 == 0 ) return n == 3 ; int u = n - 1 , t = 0 ; while (u % 2 == 0 ) u /= 2 , ++t; for (int i = 0 ; i < test_time; ++i) { int a = rand () % (n - 3 ) + 2 , v = quickPow (a, u, n); if (v == 1 ) continue ; int s; for (s = 0 ; s < t; ++s) { if (v == n - 1 ) break ; v = (long long )v * v % n; } if (s == t) return 0 ; } return 1 ; } 完整版: ll bmul (ll a, ll b, ll m) { ull c = (ull)a * (ull)b - (ull)((long double )a / m * b + 0.5L ) * (ull)m; if (c < (ull)m) return c; return c + m; } ll qpow (ll x, ll p, ll mod) { ll ans = 1 ; while (p) { if (p & 1 ) ans = bmul (ans, x, mod); x = bmul (x, x, mod); p >>= 1 ; } return ans; } bool Miller_Rabin (ll p) { if (p < 2 ) return false ; if (p == 2 ) return true ; if (p == 3 ) return true ; ll d = p - 1 , r = 0 ; while (!(d & 1 )) ++r, d >>= 1 ; for (ll k = 0 ; k < 10 ; ++k) { ll a = rand () % (p - 2 ) + 2 ; ll x = qpow (a, d, p); if (x == 1 || x == p - 1 ) continue ; for (int i = 0 ; i < r - 1 ; ++i) { x = bmul (x, x, p); if (x == p - 1 ) break ; } if (x != p - 1 ) return false ; } return true ; }
P5535 【XR-3】小道消息 - 洛谷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #include <bits/stdc++.h> using namespace std;using ll =long long ;using ull=unsigned long long ;const int inf=0x3f3f3f3f ,N = 1e6 + 5 ;ll bmul (ll a, ll b, ll m) { ull c = (ull)a * (ull)b - (ull)((long double )a / m * b + 0.5L ) * (ull)m; if (c < (ull)m) return c; return c + m; } ll qpow (ll x, ll p, ll mod) { ll ans = 1 ; while (p) { if (p & 1 ) ans = bmul (ans, x, mod); x = bmul (x, x, mod); p >>= 1 ; } return ans; } bool Miller_Rabin (ll p) { if (p < 2 ) return false ; if (p == 2 ) return true ; if (p == 3 ) return true ; ll d = p - 1 , r = 0 ; while (!(d & 1 )) ++r, d >>= 1 ; for (ll k = 0 ; k < 10 ; ++k) { ll a = rand () % (p - 2 ) + 2 ; ll x = qpow (a, d, p); if (x == 1 || x == p - 1 ) continue ; for (int i = 0 ; i < r - 1 ; ++i) { x = bmul (x, x, p); if (x == p - 1 ) break ; } if (x != p - 1 ) return false ; } return true ; } void solve () { ll n,k; cin>>n>>k; n=n+1 ; k=k+1 ; if (Miller_Rabin (k)){ if (n/k>1 ){ cout<<"2\n" ; }else { cout<<"1\n" ; } }else { cout<<"2\n" ; } } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
质因数分解(最朴素的算法) 1 2 3 4 5 6 7 8 9 10 11 12 vector<int > result; void breakdown (int n) { for (int i=2 ;i*i<=n;i++){ if (n%i==0 ){ while (n%i==0 )n/=i; result.push_back (i); } } if (n!=1 ){ result.push_back (n); } }
Pollard_Rho算法(找到数x的一个平凡因子)以下配合找到数x的最大质因子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ll max_factor, n; ll gcd (ll a, ll b) { if (b == 0 ) return a; return gcd (b, a % b); } ll Pollard_Rho (ll x) { ll s = 0 , t = 0 ; ll c = (ll)rand () % (x - 1 ) + 1 ; int step = 0 , goal = 1 ; ll val = 1 ; for (goal = 1 ;; goal *= 2 , s = t, val = 1 ) { for (step = 1 ; step <= goal; ++step) { t = (bmul (t, t, x) + c) % x; val = bmul (val, abs (t - s), x); if ((step % 127 ) == 0 ) { ll d = gcd (val, x); if (d > 1 ) return d; } } ll d = gcd (val, x); if (d > 1 ) return d; } }
数学期望 [P8774 蓝桥杯 2022 省 A] 爬树的甲壳虫 - 洛谷
期望题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ,mod=998244353 ;int f[N];int quick (int a,int b) { int res=1 ; while (b){ if (b&1 )res=res*a%mod; a=a*a%mod; b>>=1 ; } return res%mod; } void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++){ int x,y; cin>>x>>y; f[i]=((f[i-1 ]+1 )%mod*((y%mod)*quick (y-x,mod-2 )%mod)%mod)%mod; } cout<<f[n]<<endl; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }
AtCoder Link
AT_abc360_e Random Swaps of Balls - 洛谷
注意减法的同余原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=0x3f3f3f3f ,N = 1e5 + 5 ,mod=998244353 ;int f[N];int quick (int a,int b) { int res=1 ; while (b){ if (b&1 )res=res*a%mod; a=a*a%mod; b>>=1 ; } return res%mod; } void solve () { int n,k; cin>>n>>k; f[0 ]=1 ; for (int i=1 ;i<=k;i++){ f[i]=(f[i-1 ]*((n-1 )*(n-1 )%mod+1 )%mod*quick (n*n%mod,mod-2 )%mod+(2 *quick (n*n%mod,mod-2 )*(n*(n+1 )/2 %mod-f[i-1 ]%mod+mod)%mod)%mod)%mod; } cout<<f[k]<<'\n' ; } signed main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t=1 ; while (t--){ solve (); } return 0 ; }