1. 程式人生 > 實用技巧 >LeetCode——遞增的三元子序列

LeetCode——遞增的三元子序列

AEFIK

A. Groundhog and 2-Power Representation

題意

一個數可以由2x1+2x2+2x3+.....組成,例如1315=210+28+25+2+1=2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0). 現在給出一個由2的次冪組成的表示式,輸出這個數是多少。

題解

不得不說py真的強,看到不到2分鐘就有人a了,還以為是原題,賽後發現py三行。(暴風哭泣 我隊用的c++高精度模擬寫的,隊友%%%

程式碼

py
1 n = input()
2 n = n.replace("(","**(")
3 print(eval(n))
View Code

c++

  1 #include<bits/stdc++.h>
  2 #define pb push_back
  3 using namespace std;
  4 typedef long long ll;
  5 const int inf = 0x3f3f3f3f;
  6 const ll INF = 0x3f3f3f3f3f3f3f3f;
  7 const int maxn = 3e4+10;
  8  
  9 vector<int> mult(vector<int>x,vector<int>y)//高精*高精
10 { 11 int xlen=(int)x.size(),ylen=(int)y.size(),zlen=xlen+ylen; 12 vector<int>z(zlen); 13 for(register int i=0;i<xlen;i++) 14 for(register int j=0;j<ylen;j++) 15 z[i+j]+=x[i]*y[j]; 16 for(register int i=0;i<zlen;i++) 17 if(z[i]>9)
18 { 19 z[i+1]+=z[i]/10; 20 z[i]%=10; 21 } 22 while(zlen>1 && !z.back()) 23 { 24 z.pop_back(); 25 zlen--; 26 } 27 return z; 28 } 29 vector<int> chu(int x,vector<int> vv) 30 { 31 bool flag=false; 32 vector<int> ans; 33 int t=0; 34 int i; 35 for (i=vv.size()-1; i>=0; i-- ) 36 { 37 t=t*10+vv[i]; 38 if(flag) 39 { 40 ans.push_back(t/x); 41 } 42 else if(t/x>0) 43 { 44 flag=true; 45 ans.push_back(t/x); 46 } 47 t=t%x; 48 } 49 return vector<int> (ans.rbegin(),ans.rend()); 50 } 51 vector<int> add(vector<int>x,vector<int>y)//高精+高精 52 { 53 int xlen=(int)x.size(),ylen=(int)y.size(),zlen=max(xlen,ylen)+1; 54 vector<int>z(zlen); 55 for(register int i=0;i<zlen;i++) 56 { 57 if(i<xlen) 58 z[i]+=x[i]; 59 if(i<ylen) 60 z[i]+=y[i]; 61 if(z[i]>9) 62 { 63 z[i+1]++; 64 z[i]-=10; 65 } 66 } 67 while(zlen>1 && !z.back()) 68 { 69 zlen--; 70 z.pop_back(); 71 } 72 return z; 73 } 74 void prin(vector<int> x) 75 { 76 int i; 77 if(x.size() == 0) 78 { 79 printf("0"); 80 } 81 for (i=x.size()-1;i>=0;i--) 82 { 83 printf("%d",x[i]); 84 } 85 printf("\n"); 86 } 87 std::vector<int> qup(std::vector<int> vv) 88 { 89 std::vector<int> ans; 90 ans.pb(1); 91 std::vector<int> v; 92 std::vector<int> f; 93 f.pb(0); 94 v.pb(2); 95 while(vv.size() > 0 && *(--vv.end()) != 0) 96 { 97 if(vv[0] & 1) 98 ans = mult(v,ans); 99 vv = chu(2,vv); 100 v = mult(v,v); 101 } 102 return ans; 103 } 104 105 char a[maxn]; 106 vector<int> dg(int l,int r) 107 { 108 vector<int> ans; 109 110 if(l == r) 111 { 112 ans.pb(a[l] - '0'); 113 return ans; 114 } 115 ans.pb(0); 116 std::vector<int> temp; 117 for (int i = l; i <= r; i ++ ) 118 { 119 120 if(a[i] == '(') 121 { 122 int s= 0 ; 123 for(int j = i + 1; j <= r; j ++ ) 124 { 125 if(a[j] == '(') 126 s ++ ; 127 if(a[j] == ')') 128 { 129 if(s == 0) 130 { 131 ans = add(ans,qup(dg(i + 1, j - 1))); 132 i = j; 133 break; 134 } 135 else 136 s -- ; 137 } 138 } 139 continue; 140 } 141 if(a[i] == '+') 142 { 143 ans = add(ans,dg(i + 1,r)); 144 break; 145 } 146 else 147 { 148 if(a[i + 1] != '(') 149 { 150 temp.pb(a[i] - '0'); 151 ans = add(ans,temp); 152 } 153 continue; 154 } 155 } 156 return ans; 157 } 158 159 int main() 160 { 161 scanf("%s",a + 1); 162 int n = strlen(a + 1); 163 vector<int> ans = dg(1,n); 164 prin(ans); 165 }
View Code

E. Groundhog Chasing Death

題意

給出a,b,c,d,x,y,求\displaystyle\prod_{i=a}^b\prod_{j=c}^d\gcd(x^i,y^j)i=abj=cdgcd(xi,yj) modulo 998244353的結果

題解

第一想法肯定是暴力:列舉 i 和 j ,然後算出每一個 gcd(xi,yj),然後乘起來。但是資料 i 和 j 的資料範圍都在1e6,這樣肯定會超時,i 和 j 的範圍在1e9,這樣肯定是要爆long long的。那麼就要想想怎麼優化。 因為這是一個乘性函式,那麼肯定要想到分解質因子,所以先預處理 x 的質因子,並記錄每個質因子出現的次數,這樣 xi就可以由每個質因子個數再 *i 得到。列舉 xi中因子 m 出現的次數,可以發現當 yj小的時候,gcd(xi,yj) 主要是被 yj的 m 個數約束,此時是一個等差數列;當yj大的時候,就是由xi約束,此時 yj中 m 的個數是一個常數,暴力求解就好了。 由於質因子的冪很大,會爆long long,所以要用尤拉降冪,尤拉降冪是對mod-1取模(隊友對mod取模debug好久

程式碼

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3  
  4 typedef long long ll;
  5 const ll mod = 998244353;
  6 const ll md = 998244352;
  7 vector<pair<ll,ll> > v;
  8  
  9 void div(ll n)
 10 {
 11     v.clear();
 12     ll k = sqrt(n);
 13     for (ll i = 2; i <= k; ++ i) {
 14         ll cnt = 0;
 15         while (n % i == 0) {
 16             n /= i;
 17             cnt ++;
 18         }
 19         v.push_back({i, cnt});
 20     }
 21     if (n != 1) {
 22         v.push_back({n, 1});
 23     }
 24 }
 25  
 26 ll phi(ll n)
 27 {
 28     ll ans = n;
 29     ll k = sqrt(n);
 30     for (int i = 2; i <= k; ++i) {
 31         if (n % i == 0) {
 32             ans = ans / i * (i - 1);
 33             while (n % i == 0) n /= i;
 34         }
 35     }
 36     if (n > 1) {
 37         ans = ans / n * (n - 1);
 38     }
 39     return ans;
 40 }
 41  
 42 ll pow(ll a, ll b, ll p) {
 43     ll res = 1;
 44     while (b) {
 45         if (b & 1) res = (res * a) % p;
 46         a = a * a % p;
 47         b >>= 1;
 48     }
 49     return res%p;
 50 }
 51  
 52 int main()
 53 {
 54     ll a, b, c, d, x, y;
 55     scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &x, &y);
 56     a = max(1LL, a);
 57     c = max(1LL, c);
 58     --c;
 59     div(x);
 60     ll ans = 1;
 61     for (int i = 0; i < (int)v.size(); ++ i) {
 62         ll cnt = 0;
 63         while (y % v[i].first == 0) {
 64             y /= v[i].first;
 65             ++ cnt;
 66         }
 67         ll sum = 0;
 68         if (cnt == 0) continue;
 69         for (ll j = a; j <= b; ++ j) {
 70             ll e = v[i].second * (ll)j;
 71             ll f = e/cnt;
 72             while (cnt * f < e) {
 73                 ++ f;
 74             }
 75             if (c >= f) {
 76                 sum -= ((f * (f-1) / 2)% md * (cnt % md)) % md;
 77                 sum = (sum % md + md) % md;
 78                 sum -= (ll)(((c-f+1) % md) * (e % md)) % md;
 79                 sum = (sum % md + md) % md;
 80             }
 81             else {
 82                 sum -= ((c * (c+1) / 2) % md * (cnt % md)) % md;
 83                 sum = (sum % md + md) % md;
 84             }
 85             sum = (sum % md + md) % md;
 86             if (d >= f) {
 87                 sum += ((f * (f-1) / 2) % md) * (cnt % md) % md;
 88                 sum = (sum % md + md) % md;
 89                 sum += (ll)(((d-f+1) % md) * (e % md)) % md;
 90                 sum = (sum % md + md) % md;
 91             }
 92             else {
 93                 sum += (((d * (d+1) /2) % md) * (cnt) % md) % md;
 94                 sum = (sum % md + md) % md;
 95             }
 96         }
 97         sum = (sum % md + md) % md;
 98         ans *= pow(v[i].first, sum, mod);
 99         ans = (ans % mod + mod) % mod;
100     }
101     ans = (ans % mod + mod) % mod;
102     printf("%lld\n", ans);
103     return 0;
104 }
View Code

F.Groundhog Looking Dowdy

題意

土撥鼠要和蘋果約會,第 i 天它的第 j 件衣服的邋遢度為 aij,它要在n天中選擇m天和蘋果約會,要求選出的m天衣服的邋遢度的最大值和最小值的差值最小。

題解

因為要最小化最大值和最小值的差值,所以用pair存每件衣服的邋遢度和第幾天,然後對邋遢度從小到大排序。那麼問題就轉換成了求一個區間 [L,R] ,使得這個區間覆蓋m個不同的天,並且R的邋遢度-L的邋遢度最小。這個問題就可以用尺取解決了。對於每一個L,求出最小的合法的R,每次更新差值最小值即可。

程式碼

 1 #include<bits/stdc++.h>
 2 #define st first
 3 #define sd second
 4 #define ll long long
 5 #define pii pair<int,int>
 6 using namespace std;
 7  
 8 const int inf = 0x3f3f3f3f;
 9 const int maxn = 2e6+10;
10  
11 pii pp[maxn];
12 int vis[maxn];
13  
14 int main()
15 {
16     int n,m;
17     scanf("%d%d",&n,&m);
18     int cnt = 0;
19     for (int i = 1; i <= n; i ++ ){
20         int p;
21         scanf("%d",&p);
22         for (int j = 1; j <= p; j ++ ){
23             int x;
24             scanf("%d",&x);
25             pp[++cnt].st = x;
26             pp[cnt].sd = i;
27         }
28     }
29     sort(pp + 1, pp + 1 + cnt);
30     int num = 0;
31     int l = 1, r = 1;
32     int minn = pp[1].st, maxx = 0;
33     int ans = inf;
34     while(1){
35         while(r <= cnt && num < m){
36             if(vis[pp[r].sd] == 0) num ++ ;
37             vis[pp[r].sd] ++ ;
38             maxx = pp[r].st;
39             r ++ ;
40         }
41         if(num < m)
42             break;
43         ans = min(ans, maxx - minn);
44         vis[pp[l].sd] -- ;
45         if(vis[pp[l].sd] == 0) num -- ;
46         minn = pp[l + 1].sd;
47         l ++ ;
48     }
49     printf("%d\n",ans);
50 }
View Code

I.The Crime-solving Plan of Groundhog

題意

給出n個數(0<=a[i]<=9),由這n個數組成2個數,使得這兩個數的乘積最小。

題解

自己造幾個例子就可以看出,選擇0之外最小的數和剩下的數字組成的沒有前導0的數相乘結果最小。剩下的數字怎樣最小呢,當然是找到最小的非零的數做第一位,後邊接上所有的0,再按照有小到大的順序放剩下的數字。因為n的範圍在1e5,所以要用高精度乘法。

推導:

把當前的數字拆成4個數 a, b, c, d (a ≤ b ≤ c ≤ d) ,那麼我們有兩種決策:兩位數×兩位數,或者三位數×一 位數。 (10a + d) * (10b + c) = 100ab + 10ac + 10bd + cd (100b+10c+d) * a = 100ab + 10ac +ad<(10a + d) * (10b + c) 同理,可以證明留一個最小的正整數作為第一個數,剩下的所有數字排成最小的數作為第二個數時,答案取到最小值。

程式碼

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4  
 5 int a[100100];
 6  
 7 int main()
 8 {
 9     ios::sync_with_stdio(false);
10     cin.tie(0);
11     cout.tie(0);
12     int t;
13     cin>>t;
14     while(t--){
15         int n;
16         cin>>n;
17         for(int i=0;i<n;i++) cin>>a[i];
18         sort(a,a+n);
19         int k=0;
20         while(k<n&&a[k]==0) k++;
21         vector<int>q;
22         q.push_back(a[k+1]);
23         for(int i=0;i<k;i++) q.push_back(0);
24         for(int i=k+2;i<n;i++) q.push_back(a[i]);
25         vector<int>ans;
26         for(int i=q.size()-1;i>=0;i--){
27             int x=q[i]*a[k];
28             ans.push_back(x);
29         }
30         for(int i=0;i<10;i++) ans.push_back(0);
31         for(int i=0;i<ans.size();i++){
32             if(ans[i]>=10){
33                 ans[i+1]+=ans[i]/10;
34                 ans[i]%=10;
35             }
36         }
37         while(!ans.back()) ans.pop_back();
38         for(int i=ans.size()-1;i>=0;i--) cout<<ans[i];
39         cout<<endl;
40     }
41     return 0;
42 }
View Code

K.The Flee Plan of Groundhog

題意

土撥鼠在第1個宿舍,橙子在第n個宿舍。這n個宿舍間有n-1條路並且長度都為1,土撥鼠從第1個房間去第n個宿舍,速度為1m/s;橙子從第n個宿舍追趕土撥鼠,速度為2m/s。

題解

二分時間 t ,然後判斷在 ts 內土撥鼠是否會被橙子追上。以橙子所在的寢室 n 為根建樹,從 1 到 n 列舉所有土撥鼠能夠到達的點,先找出t秒能走到哪個點,然後再找這個點能走到的離n最遠的點,判斷在走的過程中會不會被追上。

程式碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 const int maxn = 1e5+10;
 5 vector<int> vv[maxn];
 6 int vis[maxn];
 7 int f[maxn];
 8 int dep[maxn];
 9  
10 void dfs(int x,int fa,int de)
11 {
12     f[x] = fa;
13     dep[x] = de;
14     for (int i =0 ; i< vv[x].size(); i ++ )
15     {
16         int v = vv[x][i];
17         if(v == fa)
18             continue;
19         dfs(v,x,de + 1);
20         vis[x] |= vis[v];
21     }
22 }
23 int ans =0 ;
24 void dfs2(int x,int fa,int de)
25 {
26     ans = max(ans,de);
27     for (int i =0 ; i<vv[x].size(); i ++ )
28     {
29         int v = vv[x][i];
30         if(v == fa)
31             continue;
32         dfs2(v,x,de + 1);
33     }
34  
35 }
36 int main()
37 {
38     int n,m;
39     scanf("%d%d",&n,&m);
40     for (int i = 1; i < n; i ++ )
41     {
42         int x,y;
43         scanf("%d%d",&x,&y);
44         vv[x].push_back(y);
45         vv[y].push_back(x);
46     }
47     vis[1] = 1;
48     dfs(n,0,1);
49     int k = -1;
50     int s = dep[1] - m;
51     for (int i = 1; i <= n; i ++ ){
52         if(vis[i] && dep[i] == s){
53             k = i;
54             break;
55         }
56     }
57     int num = dep[k] - 1;
58     dfs2(k,f[k],1);
59     ans -- ;
60     num += ans;
61     int r = (num + 1) / 2;
62     int l = 0;
63     while(l < r){
64         int mid = l + r>> 1;
65         int x = min(2 * mid,num);
66         int y = min(mid, ans);
67         if(x - dep[k] + 1>= y) r = mid;
68         else l = mid + 1;
69     }
70     printf("%d\n",l);
71 }
View Code