牛客小白月赛20

有一说一最近状态确实不太行,打了这么久还是停留在初等小白。

A.斐波那契

求斐波那契数列前n项的平方和。这是斐波那契数列面积的应用,就是求f[n] * f[n + 1],用俩次矩阵快速幂求得。o(logn)

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int N = 2;
 8 const ll mod = 1e9 + 7;
 9 
10 ll n;
11 
12 ll temp[N][N], res[N][N];
13 
14 void muti(ll a[][N], ll b[][N], int n)
15 {
16     memset(temp, 0, sizeof(temp));
17     for (ll i = 0; i < n; i ++)    
18     {
19         for (ll j = 0; j < n; j ++)
20         {
21             for (ll k = 0; k < n; k ++)
22             {
23                 temp[i][j] += (a[i][k] * b[k][j]) % mod;
24             }
25             temp[i][j] %= mod;
26         }
27     }
28     for (ll i = 0; i < n; i ++)
29         for(ll j = 0; j < n; j ++)
30             a[i][j] = temp[i][j];
31 }
32 
33 void Pow(ll a[][N], ll m, int n)
34 {
35     memset(res, 0, sizeof(res));
36     for (ll i = 0; i < n; i ++) res[i][i] = 1;
37     while(m)
38     {
39         if(m& 1) muti(res, a, n);
40         muti(a, a, n);
41         m >>= 1;
42     }
43 }
44 
45 int main()
46 {
47     scanf("%lld", &n);
48     ll a[N][N];
49     a[0][0] = 1, a[0][1] = 1, a[1][0] = 1, a[1][1] = 0;
50     Pow(a, n, 2);
51     ll ans1 = res[1][0];
52     a[0][0] = 1, a[0][1] = 1, a[1][0] = 1, a[1][1] = 0;
53     Pow(a, n + 1, 2);
54     ll ans2 = res[1][0];
55     printf("%lld\n", ((ans1 % mod ) * (ans2 % mod)) % mod);
56  } 
View Code

 

B.最大边长

打的时候不知道为什么被这样的题卡了很久。假设x < y,那么在x 上只能存在一个正方形,y存在3个, 或者x存在两个, y存在两个。反之也成立。

 1 //#include<bits/stdc++.h>
 2 #pragma GCC optimize(2)
 3 #pragma G++ optimize(2)
 4 #include<map>
 5 #include<set>
 6 #include<cmath>
 7 #include<ctime>
 8 #include<queue>
 9 #include<stack>
10 #include<cstdio>
11 #include<random>
12 #include<string>
13 #include<vector>
14 #include<cstring>
15 #include<utility>
16 #include<iostream>
17 #include<algorithm>
18 #include<functional>
19 #include<unordered_map>
20 #include<unordered_set>
21 using namespace std;
22  
23 #define ios ios::sync_with_stdio(false)
24 #define ll long long
25 #define pa pair<int,int>
26 #define mk make_pair
27 #define sc(n) scanf("%d",&n)
28 #define ss(s) scanf("%s",s)
29 #define fo(i, a, b) for(int i = a; i <= b; i++)
30 #define of(i, a, b) for(int i = a; i >= b; i--)
31 #define mem(a, b) memset(a, b, sizeof a)
32 #define copy(a,b) memcpy(a, b, sizeof b)
33 #define pi acos(-1)
34 #define input freopen("input.in", "r", stdin);
35 #define output freopen("output.out", "w", stdout);
36  
37 const ll inf = 0x3f3f3f3f;
38 const ll mod = 1e9 + 7;
39 const ll N = 2e5 + 10;
40 const ll M = 1e4 + 10;
41 const double eps = 1e-10;
42  
43 using namespace std;
44  
45 int t, n;
46  
47 int main()
48 {
49     ll a, b, c;
50     cin >> a >> b;
51     ll ans = 0;
52     if (a / 3 >= b)
53         ans = max(ans, b);
54     if (b / 3 >= a)
55         ans = max(ans, a);
56     if (b / 2 * 2 <= a)
57         ans = max(ans, b / 2);
58     if (a / 2 * 2 <= b)
59         ans = max(ans, a / 2);
60     cout << ans << endl;
61     return 0;
62 }
View Code

 

C.球的表面积

做这题必须知道球冠的表面积公式2πRH, R为球半径,H为球冠的高。若两个球相离,则是面积相加。若包含关系,则输出较大的面积。若相加,就是俩个球冠的表面积被除去。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<string>
 6 #include<vector>
 7 #include<math.h>
 8 using namespace std;
 9 #define ll long long
10 #define PI  3.1415926
11 int main()
12 {
13    double x1,y1,z1,r1,x2,y2,z2,r2;
14    scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&z1,&r1,&x2,&y2,&z2,&r2);
15    double ans1=4*PI*r1*r1;
16    double ans2=4*PI*r2*r2;
17    double len=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
18    if(len>=r1+r2)
19    {
20        printf("%.6lf\n",ans1+ans2);
21    }
22    else if((len<r1+r2)&&(len>max(r1,r2)-min(r1,r2)))
23    {
24        double cosa=(r1*r1+len*len-r2*r2)/(2*r1*len*1.00000);
25        double dis1=cosa*r1;
26        double h1=r1-dis1;
27        double s1=ans1-2*PI*r1*h1;
28  
29        double cosb=(r2*r2+len*len-r1*r1)/(2*r2*len*1.00000);
30        double dis2=cosb*r2;
31        double h2=r2-dis2;
32        double s2=ans2-2*PI*r2*h2;
33        printf("%.6lf\n",s1+s2);
34    }
35    else if(len<=max(r1,r2)-min(r1,r2))
36    {
37        printf("%lf\n",max(ans1,ans2));
38    }
39 }
View Code

 

D.3的倍数

发现n很小,直接暴力。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int n;
 6 char s[20][10010];
 7 
 8 int f[20][36];
 9 int res[36];
10 int ans;
11 
12 bool check()
13 {
14     for (int i = 1; i <= 26; i ++)
15     {
16         if(res[i] % 3) return false;
17     }
18     return true;
19 }
20 
21 void dfs(int u, int cnt)
22 {
23     if(u == n + 1)
24     {
25         if(check())
26         ans = max(ans, cnt);
27         return ;    
28     }
29     for (int j = 1; j <= 26; j ++) res[j] += f[u][j];
30     dfs(u + 1, cnt + 1);
31     for (int j = 1; j <= 26; j ++) res[j] -= f[u][j];
32     dfs(u + 1, cnt);    
33 }
34 
35 int main()
36 {
37     scanf("%d", &n);
38     for (int i = 1; i <= n; i ++)
39     {
40         scanf("%s", s[i] + 1);
41         int len = strlen(s[i] + 1);
42         for (int j = 1; j <= len; j ++)
43         {
44             f[i][s[i][j] - 'A' + 1] ++;
45         }
46     }
47     dfs(1, 0);
48     cout << ans << endl;
49  } 
View Code

 

E.区区区间

这题明示线段是,但是本人因为最近学了分块,结果一直想要分块,结果自闭住。其实线段树比较好想,用lazy数组去维护区间最左端的值。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int N = 2e5 + 10;
 8 
 9 int n, m;
10 ll a[N];
11 ll sum[N << 2], lazy[N << 2];
12 
13 void pushup(int rt)
14 {
15     sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
16 }
17 
18 void pushdown(int rt, int llen, int rlen)
19 {
20     if(lazy[rt])
21     {
22         lazy[rt << 1] = lazy[rt];
23         lazy[rt << 1 | 1] = lazy[rt] + llen;
24         sum[rt << 1] = 1ll * (lazy[rt] + lazy[rt] + llen - 1) * llen / 2;
25         sum[rt << 1 | 1] = 1ll * (lazy[rt << 1 | 1] + lazy[rt << 1 | 1] + rlen - 1) * rlen / 2;
26         lazy[rt] = 0;
27     }
28 }
29 
30 void build(int l, int r, int rt)
31 {
32     if(l == r)
33     {
34         sum[rt] =  a[l];
35         lazy[rt] = 0;
36         return ;
37     }
38     int mid = l + r >> 1;
39     build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
40     pushup(rt);
41 }
42 
43 ll query(int L, int R, int l, int r, int rt)
44 {
45     ll ans = 0;
46     if(L <= l && R >= r)
47     {
48         return sum[rt];
49     }
50     int mid = l + r >> 1;
51     pushdown(rt, mid - l + 1, r - mid);
52     if(L <= mid) ans += query(L, R, l, mid, rt << 1);
53     if(R > mid)     ans += query(L, R, mid + 1, r, rt << 1 | 1);
54     return ans;
55 }
56 
57 void update(int L, int R, int C,int l, int r, int rt)
58 {
59     if(L <= l && R >= r)
60     {
61         sum[rt] = 1ll * (r - l + 1) * (C - L + l + C - L + l + r - l) / 2;
62         lazy[rt] = C - L + l;
63         return ;
64     }
65     int mid = l + r >> 1;
66     pushdown(rt, mid - l + 1, r - mid);
67     if(L <= mid) update(L, R, C, l, mid, rt << 1);
68     if(R > mid)     update(L, R, C, mid + 1, r, rt << 1 | 1);
69     pushup(rt);
70 }
71 
72 int main()
73 {
74     scanf("%d%d", &n, &m);
75     for (int i = 1; i <= n; i ++)
76         scanf("%lld", &a[i]);
77     build(1, n, 1);
78     while(m --)
79     {    
80         int op;
81         scanf("%d", &op);
82         if(op == 1)
83         {
84             int l, r, k;
85             scanf("%d%d%d", &l, &r, &k);
86             update(l, r, k, 1, n, 1);
87         }
88         else
89         {
90             int l, r;
91             scanf("%d%d", &l, &r);
92             printf("%lld\n", query(l, r, 1, n, 1));
93         }
94     }    
95  } 
View Code

 

F.进制转换

用短除法。基本操作。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int n, m, k;
 6 
 7 char s[2200];
 8 
 9 vector<int>a;
10 
11 int main()
12 {
13     scanf("%s", s + 1);
14     scanf("%d%d", &m, &k);
15     int len = strlen(s + 1);
16     for (int i = len; i >= 1; i --)
17     {
18         if(s[i] >= '0' && s[i] <= '9')
19         {
20             a.push_back(s[i] - '0');
21         }
22         else if(s[i] >= 'a' && s[i] <= 'z')
23         {
24             a.push_back(s[i] - 'a' + 10);
25         }
26     }
27     vector<int> res;
28     while(a.size())
29     {
30         int t = 0;
31         for (int i = a.size() - 1; i >= 0; i --)
32         {
33             a[i] += t * m;
34             t = a[i] % k;
35             a[i] /= k;
36         }
37         res.push_back(t);
38         while(a.size() && !a.back()) a.pop_back();
39     }
40     reverse(res.begin(), res.end());
41     string b_line;
42         for (auto x : res )
43         {
44                if (x <= 9) b_line += char('0' + x);
45             else b_line += char('a' + x - 10);
46         }
47         cout << b_line << endl;
48 }
View Code

 

G.快乐风男

求最长严格上升子序列字典序最小的。那么直接贪心,先二分求出每个a[i]应该出现在上升数组的哪个位置。然后对位置进行贪心。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 1e5 + 10;
 6 const int INF = 0x3f3f3f3f;
 7 
 8 int n;
 9 int a[N], cnt, f[N];
10 
11 int len[N], first[N];
12 int ans[N];
13 
14 int main()
15 {
16     memset(f, 0x3f, sizeof(f));
17     scanf("%d", &n);
18     for (int i = 1; i <= n; i ++)
19         scanf("%d", &a[i]);
20     for (int i = 1; i <= n; i ++)
21     {
22         int t = lower_bound(f + 1, f + n + 1, a[i]) - f;
23         if(f[t] == INF)
24         {
25             ++ cnt;
26             f[t] = a[i];
27             len[i] = t;
28         }
29         else
30         {
31             f[t] = a[i];
32             len[i] = t;
33         }
34         if(first[len[i]] == 0) first[len[i]] = i;
35     }
36     printf("%d\n", cnt);
37     ans[cnt] = first[cnt];
38     for (int i = first[cnt] - 1; i >= 1; i --)
39     {
40         if(a[i] < a[ans[len[i] + 1]])
41         ans[len[i]] = i;
42      }
43     for(int i = 1; i <= cnt; i++)
44     printf("%d%c", ans[i], i==cnt?'\n':' ');
45 } 
View Code

 

H.好点

类似二位偏序,只要求右上角不存在的情况,那么按横坐标从小到大,从后往前开始记录,若它的纵坐标最大,其右上角一定不存在点。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 5e5 + 100;
 5 const int mod = 1e9 + 7;
 6 int n, m;
 7 struct node{
 8     int x, y;
 9     bool operator<(const node &a)const{
10         return x < a.x;
11     }
12 }a[maxn],ans[maxn];
13 int main(){
14     cin >> n;
15     for (int i = 1; i <= n; i++)
16         scanf("%d%d", &a[i].x, &a[i].y);
17     sort(a + 1, a + 1 + n);
18     int my = -1e9-1;
19     int num = 0;
20     for (int i = n; i>= 1; i--){
21         if (a[i].y > my){
22             my = a[i].y;
23             ans[++num].x = a[i].x;
24             ans[num].y = a[i].y;
25         }
26     }
27     sort(ans + 1, ans + 1 + num);
28     for (int i = 1; i <= num; i++)
29         cout << ans[i].x << " " << ans[i].y << endl;
30     return 0;
31 }
View Code

 

I.小小小马

对于n <= 3 && m <= 3(除了n == 1 && m == 1)都不可行,其余都可行。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef pair<int, int> PII;
 6 
 7 const int N = 2e3 + 10;
 8 
 9 int n, m; 
10 
11 bool st[N][N];
12 
13 
14 int main()
15 {    
16     scanf("%d%d", &n, &m);
17     if(n == 1 && m == 1)
18     {
19         puts("Yes");
20         return 0;
21     }
22     if(n == 1 || m == 1)
23     {
24         puts("No");
25         return 0;
26     }
27     if(n == 2 || m == 2)
28     {
29         puts("No");
30         return 0;
31     }
32     if(n <= 3 && m <= 3)
33     {
34         puts("No");
35         return 0;
36     }
37     puts("Yes");
38     
39  } 
View Code

 

J.dh的帽子

典型的数位DP,一个上界一个下界。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 ll dp[32][2][2][2][2][2][2];
 8 int num1[32], num2[32];
 9 
10 
11 ll dfs(int len, bool lim1, bool lim2, bool lim3, bool im1, bool im2, bool im3)
12 {
13     if(len == -1) return 1;
14     if(dp[len][lim1][lim2][lim3][im1][im2][im3] != -1) return dp[len][lim1][lim2][lim3][im1][im2][im3];
15     ll ans = 0;
16     int up1 = lim1 ? num2[len] : 1;
17     int up2 = lim2 ? num2[len] : 1;
18     int up3 = lim3 ? num2[len] : 1;
19     int down1 = im1 ? num1[len] : 0;
20     int down2 = im2 ? num1[len] : 0;
21     int down3 = im3 ? num1[len] : 0;
22     for (int i = 0; i <= up1; i ++)
23         for (int j = 0; j <= up2; j ++)
24             for (int k = 0; k <= up3; k ++)
25                 {
26                     if(i < down1 || j < down2 || k < down3) continue;
27                     if((i ^ j ^ k) != (i | j | k)) continue;
28                     ans += dfs(len - 1, lim1 && i == up1, lim2 && j == up2, lim3 && k == up3, im1 && i== down1, im2 && j == down2, im3 && k == down3);
29                 }
30     return dp[len][lim1][lim2][lim3][im1][im2][im3] = ans;
31 }
32 
33 //ll dfs(int len, bool limit1, bool limit2, bool limit3, bool ismin1, bool ismin2, bool ismin3)
34 //{
35 //    if (len == -1)
36 //        return 1;
37 //        
38 //    if (dp[len][limit1][limit2][limit3][ismin1][ismin2][ismin3] != -1)
39 //        return dp[len][limit1][limit2][limit3][ismin1][ismin2][ismin3];
40 //        
41 //    int up1 = limit1 ? num2[len] : 1;
42 //    int up2 = limit2 ? num2[len] : 1;
43 //    int up3 = limit3 ? num2[len] : 1;
44 //    int un1 = ismin1 ? num1[len] : 0;
45 //    int un2 = ismin2 ? num1[len] : 0;
46 //    int un3 = ismin3 ? num1[len] : 0;
47 //    ll ans = 0;
48 //    for (int i = 0; i <= up1; i++)
49 //    {
50 //        for (int j = 0; j <= up2; j++)
51 //        {
52 //            for (int l = 0; l <= up3; l++)
53 //            {
54 //                if (i < un1 || j < un2 || l < un3)
55 //                    continue;
56 //                if ((i ^ j ^ l) != (i | j | l))
57 //                    continue;
58 //                ans += dfs(len - 1, limit1 && i == up1, limit2 && j == up2, limit3 && l == up3, ismin1 && i == un1, ismin2 && j == un2, ismin3 && l == un3);
59 //            }
60 //        }
61 //    }
62 //    return dp[len][limit1][limit2][limit3][ismin1][ismin2][ismin3] = ans;
63 //}
64 
65 
66 ll solve(int l, int r)
67 {
68     for (int i = 0; i <= 30; i ++)
69     {
70         num1[i] = (l >> i) & 1;
71         num2[i] = (r >> i) & 1;
72 //        cout << num1[i] << " " << num2[i] << endl;
73     }
74     return dfs(30, true, true, true, true, true, true);
75 }
76 
77 int main()
78 {
79     int l, r;
80     memset(dp, -1, sizeof(dp));
81     scanf("%d%d", &l, &r);
82     printf("%lld\n", solve(l, r));
83 }
View Code

 

K.Hellow World

就真Hellow Horld。

posted @ 2019-12-23 00:08  逾期不候丶  阅读(370)  评论(0编辑  收藏  举报