2022-02-16每日刷题打卡

67 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

2022-02-16每日刷题打卡

AcWing——算法基础

338. 计数问题 - AcWing题库

给定两个整数 a 和 b,求 a 和 b 之间的所有数字中 0∼9 的出现次数。

例如,a=1024,b=1032,则 a 和 b 之间共有 9个数如下:

1024 1025 1026 1027 1028 1029 1030 1031 1032

其中 0 出现 10 次,1 出现 10 次,2 出现 7 次,3 出现 3 次等等…

输入格式

输入包含多组测试数据。

每组测试数据占一行,包含两个整数 aa 和 bb。

当读入一行为 0 0 时,表示输入终止,且该行不作处理。

输出格式

每组数据输出一个结果,每个结果占一行。

每个结果包含十个用空格隔开的数字,第一个数字表示 0 出现的次数,第二个数字表示 1 出现的次数,以此类推。

数据范围

0<a,b<100000000

输入样例:

1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0

输出样例:

1 2 1 1 1 1 1 1 1 1
85 185 185 185 190 96 96 96 95 93
40 40 40 93 136 82 40 40 40 40
115 666 215 215 214 205 205 154 105 106
16 113 19 20 114 20 20 19 19 16
107 105 100 101 101 197 200 200 200 200
413 1133 503 503 503 502 502 417 402 412
196 512 186 104 87 93 97 97 142 196
398 1375 398 398 405 499 499 495 488 471
294 1256 296 296 296 296 287 286 286 247

这题的思路挺简单的,依次统计每一个数在某个位置上的出现次数,比如数字1在第二个位置上的出现次数,拿11345到12345来举例,第二位上是1的范围是11345到11999,那么1在第二位上就出现了11999-11345+1次,如果是20345到25345,那么第二位是1的范围就是21000到21999,即21999-21000+1次,既可以通过这种方法很快的得出某个数在某个位置上的出现次数,那么我们只要计算一个数在所有位置上的和,就可以得出这个数的出现次数了。

#include<iostream>
using namespace std;
#include<vector>

int pow10(int i)
{
    int res=1;
    while(i--)res*=10;
    return res;
}

int get(vector<int>&v,int l,int r)
{
    int res=0;
    for(int i=l;i>=r;i--)res=res*10+v[i];
    return res;
}

int count(int num,int x)
{
    if(!num)return 0;
    int res=0;
    vector<int>v;
    int n=num;
    while(n)
    {
        v.push_back(n%10);
        n/=10;
    }
    n=v.size();
    for(int i=n-1-!x;i>=0;i--)
    {
        if(i<n-1)
        {
            res+=get(v,n-1,i+1)*pow10(i);
            if(!x)res-=pow10(i);
        }
        
        if(v[i]==x)res+=get(v,i-1,0)+1;
        else if(v[i]>x)res+=pow10(i);
    }
    return res;
}

int main()
{
    int a,b;
    while(cin>>a>>b&&a!=0&&b!=0)
    {
        if(a>b)swap(a,b);
        for(int i=0;i<10;i++)
            cout<<count(b,i)-count(a-1,i)<<" ";
        cout<<endl;
    }
    return 0;
}

285. 没有上司的舞会 - AcWing题库

Ural 大学有 N 名职员,编号为 1∼N。

他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。

每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。

现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。

在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。

输入格式

第一行一个整数 N。

接下来 N 行,第 i 行表示 i 号职员的快乐指数 Hi。

接下来 N−1 行,每行输入一对整数 L,K,表示 K 是 L 的直接上司。

输出格式

输出最大的快乐指数。

数据范围

1≤N≤6000
−128≤Hi≤127

输入样例:

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5

输出样例:

5

这题按思路来说就是,选了上司就不能选他的下属,但是可以选他下属的下属(我附庸的附庸不是我的附庸),就看怎么选,得到的快乐值总和最大,写起来就像树形的打家劫舍(打家劫舍问题:一个小偷偷一排房屋,不能偷相邻的,即如果ab相邻,那么你要是偷了a就不能偷b,问怎么偷得到的钱最多)

#include<iostream>
using namespace std;
#include<cstring>

const int N=6010;
int happy[N],idx,ne[N],e[N],f[N][2],h[N];
bool father[N];

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u)
{
    f[u][1]=happy[u];
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        dfs(j);
        f[u][0]+=max(f[j][0],f[j][1]);
        f[u][1]+=f[j][0];
    }
}

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>happy[i];
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++)
    {
        int a,b;
        cin>>a>>b;
        add(b,a);
        father[a]=true;
    }
    int res=1;
    while(father[res])res++;
    dfs(res);
    cout<<max(f[res][0],f[res][1])<<endl;
    return 0;
}

蓝桥杯——算法提高

算法提高 阶乘模

问题描述

给定n和p,输出n!对p取余的结果。

输入格式

一行两个数n和p。

输出格式

一行一个数表示结果。

样例输入

6 10000

样例输出

720

数据规模和约定

n<=10000000,p<=10000。

直接一边算阶乘一边取模就行。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string.h>
#include<string>
#include<math.h>

int main()
{
    int a, b,res=1;
    cin >> a >> b;
    for (int i = 1; i <= a; i++)
    {
        res *= i;
        res %= b;
    }
    cout << res << endl;

    return 0;
}