2021暑假算法学习笔记(基础复习)#1

2021-07-06

过了一下基础算法,然后去做英文题拯救自己的阅读能力。

CodeForces-1513A Array and Peaks

本题阅读无障碍。

思路:一个1到n的顺序排列,当需要peak时直接交换相邻两个数即可,如下所示:

1,(2, 3),(4,5),(6,7),(8,9),10

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int t;
int n, k;

void print()
{
    int t = 0;
    printf("1 ");
    for (int i = 2; i <= n; i ++ )
    {
        if (i % 2 == 0) t ++ ;//cnt_peak
        if (t <= k)
            {
                if (i % 2 == 0) printf("%d ", i + 1);
                else printf("%d%c", i - 1, i == n ? '\n' : ' ');
            }
        else printf("%d%c", i, i == n ? '\n' : ' ');
    }
}

int main()
{
    cin >> t;
    while (t -- )
    {
        cin >> n >> k;
        
        if (n % 2)//奇数
            if (k > (n - 1) / 2)
            {
                puts("-1");
                continue;
            }
            else
            {
                if (n == 1)
                {
                    puts("1");
                    continue;
                }
                print();
            }
        else
        {
            if (k > (n - 2) / 2)
            {
                puts("-1");
                continue;
            }
            else print();
        }
    }
    
    return 0;
}
CodeForces-1511A Review Site

阅读无障碍。manipulate——操作

思路:直接统计1 和 3的个数就行

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int t;

int main()
{
    scanf("%d", &t);
    while (t -- )
    {
        int n, ans = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i ++ )
        {
            int x;
            scanf("%d", &x);
            if (x != 2) ans ++ ;
        }
        
        printf("%d\n", ans);
    }
    
    return 0;
}
CodeForces-4A Watermelon

berry——浆果

even——偶数的;同样大小的;平分的

obligatory——义务的;必须的;义不容辞的

#include <iostream>

using namespace std;

int w;

int main()
{
    cin >> w;
    if (w != 2 && w % 2 == 0) puts("Yes");
    else puts("No");
    
    return 0;
}
CodeForces-1513A Add One

思路1(tle):f[i, j]表示操作了j次,有f[i, j]个数字i,最后的答案就是f[i, m]求和,i从0到9。TLE。

tle code

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200010, MOD = 1e9 + 7;

int f[12][N];
int t;
int n, m;

int main()
{
    scanf("%d", &t);
    while (t -- )
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= 9; i ++ ) f[i][0] = 0;
        while (n)
        {
            f[n % 10][0] ++ ;
            n /= 10;
        }
        for (int j = 1; j <= m; j ++ )
        {
            f[0][j] = f[9][j - 1] % MOD;
            f[1][j] = (f[0][j - 1] + f[9][j - 1]) % MOD;
            for (int i = 2; i <= 9; i ++ ) f[i][j] = f[i - 1][j - 1] % MOD;
        }
        
        long long ans = 0;
        for (int i = 0; i <= 9; i ++ ) ans = (ans + f[i][m]) % MOD;
        printf("%lld\n", ans);
    }
    
    return 0;
}

思考:一个样例最多2e5的操作次数,时间复杂度较高。我们可以知道每个数字经过若干次变换都会变成10,所以我们不妨预处理出来10这个序列操作若干次后的长度变换情况,然后之后只需要统计数字个数,然后直接调用预处理好的信息数组即可。

每次操作如果序列边长,那么增长的数量一定是上一步9的数量,所以用sum存储序列长度,并更新。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 2e5 + 10, MOD = 1e9 + 7;

int f[N][15];//要预处理的数组
int a[15];//存储数字n的每一位
int sum[N];//存储变化i次目前长度变成了多少
int n, m;
int t;

void init()//预处理f数组
{
    f[0][0] = f[0][1] = 1, sum[0] = 2;
    for (int i = 1; i < N; i ++ )
    {
        int temp = f[i - 1][9];
        for (int j = 9; j >= 1; j -- )
            f[i][j] = f[i - 1][j - 1];
        f[i][0] = temp;
        f[i][1] = (1ll * f[i][1] + temp) % MOD;
        
        sum[i] = (1ll * sum[i - 1] + temp) % MOD;
    }
}

int main()
{
    init();
    
    scanf("%d", &t);
    while (t -- )
    {
        scanf("%d%d", &n, &m);
        
        //学习大佬博客学到的写法
        a[0] = 0;//一个含义是a数组索引,另一个含义是统计数字位数
        while (n)
        {
            a[ ++ a[0]] = n % 10;
            n /= 10;
        }
        
        LL ans = 0;
        for (int i = 1; i <= a[0]; i ++ )//看每一位
        {
            int cnt = 10 - a[i];//距离10差多少步
            
            if (m < cnt)//不够分裂
                ans = (1ll * ans + 1) % MOD;//加上这一位的长度
            else 
                ans = (1ll * ans + sum[m - cnt]) % MOD;//加上这一位变换后的长度
        }
      
        printf("%lld\n", ans);
    }
    
    return 0;
}
posted @ 2021-07-06 19:15  sunnyday0725  阅读(37)  评论(0编辑  收藏  举报