Fork me on GitHub

FJUT2019暑假周赛一题解

A.排队问题*-*

题意就是有长度为L的序列,每位的取值可以是'f'或者'm',问不包含'fff'和'fmf'的个数。

打表找规律

不难找出递推公式为F[n] = F[n-1] + F[n-3] + F[n-4]。

然后直接遍历就可以了...突然发现L范围很小,我写了个矩阵快速幂...

多组数据且模数不固定,矩阵快速幂即可

 

  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

此处应有严格证明递推公式的由来,然而我不会。。。

B.就差把标程贴上去了

公式都已经放出来了

一个数的长度也就是len(x) = log(x)/log(10) + 1,这里我们取对数就可以得到len(n!) = 1/2*log10(2.0*PI*n) + n*log10(n/e)+1。

这里其实就够了,当然你可以继续化简到和我代码一样= =

 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个部分的最大值。

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。

 

posted @ 2019-08-04 23:19  Xenny  阅读(464)  评论(0编辑  收藏  举报