FJUT2019暑假周賽一題解

A.排隊問題*-*

題意就是有長度爲L的序列,每位的取值能夠是'f'或者'm',問不包含'fff'和'fmf'的個數。ios

打表找規律c++

不難找出遞推公式爲F[n] = F[n-1] + F[n-3] + F[n-4]。
算法

而後直接遍歷就能夠了...忽然發現L範圍很小,我寫了個矩陣快速冪...數組

多組數據且模數不固定,矩陣快速冪便可ide

 

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 
 5 int n,mod;  6 
 7 struct M {  8     ll p[4][4];  9     M(int num) {  10         memset(p,0,sizeof p);  11         for (int i = 0; i < 4; i++) {  12             p[i][i] = num;  13  }  14  }  15 
 16     M operator * (M b) {  17         M c(0);  18         for (int i = 0; i < 4; i++) {  19             for (int j = 0; j < 4; j++) {  20                 c.p[i][j] = 0;  21                 for (int k = 0; k < 4; k++) {  22                     c.p[i][j] = (c.p[i][j] + (p[i][k]*b.p[k][j])%mod)%mod;  23 
 24  }  25  }  26  }  27         return c;  28  }  29 
 30     M operator ^ (ll k) {  31         M c(1),a = *this;  32         while (k) {  33             if (k&1) {  34                 c = a*c;  35  }  36             a = a*a;  37             k >>= 1;  38  }  39         return c;  40  }  41 
 42 };  43 M a(0),b(0);  44 int solve() {  45     M c(0);  46 
 47     if (n == 0) {  48         return 0;  49     } else if (n <= 4) {  50         return a.p[4-n][0]%mod;  51  }  52     c = b^(n-4);  53     c = c*a;  54     return c.p[0][0]%mod;  55 }  56 
 57 string s;  58 
 59 void db() {  60     for (int i = 1; i <= 15; i++) {  61         int p = pow(2.0,i),tot = 0,cnt = 0;  62         for (int j = 0; j < p; j++) {  63             int tmp = 1;  64             s = "";  65             for (int k = 1; k <= i; k++) {  66                 if (tmp&j) {  67                     s += 'f';  68                 } else {  69                     s += 'm';  70  }  71                 tmp <<= 1;  72  }  73             for (int k = 0; k < int(s.size())-2; k++) {  74                 if (s[k] =='f' && s[k+1] == 'm' && s[k+2] == 'f') {  75                     cnt++;  76                     break;  77                 } else if (s[k] =='f' && s[k+1] == 'f' && s[k+2] == 'f') {  78                     cnt++;  79                     break;  80  }  81  }  82             tot++;  83  }  84         cout << i << ' ' << p-cnt << endl;  85  }  86 }  87 /*
 88  f_i = f_{i-1} + f_{i-3} +f_{i-4};  89  1 0 1 1  90  1 0 0 0  91  0 1 0 0  92  0 0 1 0  93 */
 94 int main() {  95     ios_base::sync_with_stdio(0);  96     cin.tie(0);  97  db();  98 
 99     a.p[0][0] = 9; 100     a.p[1][0] = 6; 101     a.p[2][0] = 4; 102     a.p[3][0] = 2; 103     b.p[0][0] = 1; 104     b.p[0][2] = 1; 105     b.p[0][3] = 1; 106     b.p[1][0] = 1; 107     b.p[2][1] = 1; 108     b.p[3][2] = 1; 109     while (cin >> n >> mod) { 110         cout << solve() << endl; 111  } 112     return 0; 113 }
View Code

此處應有嚴格證實遞推公式的由來,然而我不會。。。this

B.就差把標程貼上去了

公式都已經放出來了spa

一個數的長度也就是len(x) = log(x)/log(10) + 1,這裏咱們取對數就能夠獲得len(n!) = 1/2*log10(2.0*PI*n) + n*log10(n/e)+1。code

這裏其實就夠了,固然你能夠繼續化簡到和我代碼同樣= =blog

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 #define pi (acos(-1))
 5 ll n,d;  6 
 7 void solve() {  8     cin >> n;  9     d = (int) ((0.5*log(2*pi*n) + n*log(n)-n) / log (10)); 10     cout << d+1 << endl; 11 } 12 
13 int main() { 14     ios_base::sync_with_stdio(0); 15     cin.tie(0); 16     int _; 17     cin >> _; 18     while (_--) { 19  solve(); 20  } 21     return 0; 22 }
View Code

 

C.假算法天下第一

搞了半天 搞懂了題意,就是一個數組分k次(至多),而後要求每部分儘可能小,再求這k個部分的最大值。ci

emmm就是一個最大值最小化問題,LRJ的《算法入門經典》裏面有詳細介紹。

 

 

咱們能夠用二分思考這道題,咱們使用二分肯定一個值x,使得x儘可能小而且每一個區間都不大於它。

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 #define pi (acos(-1))
 5 int n,k;  6 ll p[100005];  7 bool flag[100005];  8 
 9 void work(ll l, ll r) {  10     while(l < r) {  11         bool flag1 = false;  12         ll mid = (l + r) / 2;  13         ll sum = 0, kide = 1;  14 
 15         for(int i = 0; i < n; i++) {  16             if(sum < mid && sum + p[i] < mid) {  17                 sum += p[i];  18  }  19             else {  20                 if(p[i] < mid) {  21                     kide++;  22                     sum = 0;  23                     sum += p[i];  24                 } else {  25                     flag1 = true;  26                     break;  27  }  28  }  29  }  30 
 31         if(flag1 || kide > k) {  32             l = mid + 1;  33         } else {  34             r = mid;  35  }  36  }  37 
 38     ll sum = 0;  39 
 40     for(int i = n - 1; i >= 0; i--) {  41         if(sum < l && sum + p[i] < l) {  42             sum += p[i];  43  }  44         else {  45             sum = 0;  46             flag[i] = true;  47             sum += p[i];  48  }  49  }  50 
 51     int di = 1;  52     int pos = 0;  53 
 54     for(int i = n - 1; i >= 0; i--) {  55         if(flag[i]) {  56             di++;  57  }  58  }  59 
 60     if(di != k) {  61         for(int i = 0; i < n && di != k; i++) {  62             if(!flag[i]) {  63                 flag[i] = true;  64                 di++;  65  }  66  }  67  }  68 
 69     ll tmp = 0, ans = 0;  70 
 71     for(int i = 0; i < n; i++) {  72         if(flag[i] && i != n - 1) {  73             tmp += p[i];  74             ans = max(tmp, ans);  75             tmp = 0;  76         } else if(i != n - 1) {  77             tmp += p[i];  78         } else {  79             tmp += p[i];  80  }  81         //cout << tmp << endl;
 82  }  83 
 84     ans = max(tmp, ans);  85     cout << ans << endl;  86 }  87 
 88 void solve() {  89     cin >> n >> k;  90     n--;  91     ll sum = 0;  92 
 93     for(int i = 0; i < n; i++) {  94         cin >> p[i];  95         sum += p[i];  96  }  97     if (k == 1) {  98         cout << sum << endl;  99     } else { 100         work(0, sum); 101  } 102 } 103 
104 int main() { 105     ios_base::sync_with_stdio(0); 106     cin.tie(0); 107  solve(); 108     return 0; 109 }
View Code

 而後我發現了個神奇的代碼

ZB果真nb = =

D.美好的一天從WA+1開始

題意就不說了,反悔貪心的題目,首先咱們按照日期進行貪心,而後用堆維護一下選區的物品,當遇到某件物品不能選取可是他的值卻大於之前選過的某個,就進行替換。

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 #define pi (acos(-1))
 5 int n;  6 int na,nb;  7 vector<pair<int,int>> p(100005);  8 ll sum,avg;  9 
10 void init() { 11 } 12 
13 void solve() { 14     while (cin >> n) { 15         sum = 0; 16         priority_queue<int,vector<int>,greater<int>> q; 17         for (int i = 1; i <= n; i++) { 18             cin >> p[i].second >> p[i].first; 19  } 20         sort(p.begin()+1,p.begin()+1+n); 21         for (int i = 1; i <= n; i++) { 22             if (q.size() < p[i].first) { 23  q.push(p[i].second); 24                 sum += p[i].second; 25             } else { 26                 if (p[i].second > q.top()) { 27                     sum -= q.top(); 28                     sum += p[i].second; 29  q.pop(); 30  q.push(p[i].second); 31  } 32  } 33  } 34         cout << sum << endl; 35  } 36 } 37 
38 int main() { 39     ios_base::sync_with_stdio(0); 40     cin.tie(0); 41  solve(); 42     return 0; 43 }
View Code

E.矮死 發 矮死 破色波

沒什麼好說的,優先喝b就好了。

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 #define pi (acos(-1))
 5 int n,a,b;  6 int na,nb;  7 int p[200005];  8 
 9 void solve() { 10     cin >> n >> a >> b; 11     na = a; 12     nb = b; 13     for (int i = 1; i <= n; i++) { 14         cin >> p[i]; 15  } 16     for (int i = 1; i <= n; i++) { 17         if (p[i]) { 18             if (na > 0 && nb < b) { 19                 na--; 20                 nb++; 21             } else if (nb > 0) { 22                 nb--; 23             } else if (na > 0) { 24                 na--; 25             } else { 26                 cout << i-1 << endl; 27                 return; 28  } 29         } else { 30             if (nb > 0) { 31                 nb--; 32             } else if (na > 0) { 33                 na--; 34             } else { 35                 cout << i-1 << endl; 36                 return; 37  } 38  } 39  } 40     cout << n << endl; 41 } 42 
43 int main() { 44     ios_base::sync_with_stdio(0); 45     cin.tie(0); 46  solve(); 47     return 0; 48 }
View Code

排版亂糟糟的,很久沒寫博客了= =,數學公式將就着看看吧= =,我也不知道博客園怎麼弄Latex。

相關文章
相關標籤/搜索