hiho[Offer收割]编程练习赛30

时间:2023-02-13 17:54:59

题目1 : 提取用户名

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在现在的各种互联网应用中,在一段文字中使用'@'字符来提起一名用户是流行的做法。  

例如:

"@littleho submitted his code 30 times before he got passed the system test."  

其中littleho就是一个用户名。我们规定在一段文字中,'@'字符之后一段连续的、非空的大小写英文字母组成的字符串被视为提起的用户名。  

给定一段文字,请你输出其中所有提到的用户名。

输入

一行文本,只包含大小写字母、标点符号和空格。长度不超过800。

输出

按文本中的顺序输出所有提到的用户名,之间用一个空格隔开。重复提到的相同用户名也重复输出。

样例输入
@abc:@@,@littleho's code is so confusing. @abc.
样例输出
abc littleho abc

无脑模拟,直接写就好了,但是要记得回退

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    getline(cin,s);
    for(int i=0;s[i];i++)
    {
        if(s[i]=='@')
        {
            string c;
            i++;
            for(;s[i];i++)
                if(s[i]>='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z')
                    c+=s[i];
                else break;
            if(c.length())
                {cout<<c<<" ";}
            if(s[i]=='@')i--;
        }

    }
    return 0;
}

题目2 : 股票价格II

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi最近在关注股票,为了计算股票可能的盈利,他获取了一只股票最近N天的价格A1~AN。

在小Hi的策略中,每天可以在下列三种操作中选取一种:

1.什么也不做;

2.按照当天的价格买进一个单位的股票;

3.按照当天的价格卖出部分或所有股票。

现在小Hi希望能够知道,如果在N天前手中持有的股票数为0,并且假设拥有无限的金钱,在这N天结束能够获得的最大利润是多少?

输入

第一行包含一个整数N。  

第二行包含N个整数,A1, A2, ... AN。  

对于30%的数据, 1 ≤ N ≤ 103  

对于100%的数据,1 ≤ N ≤ 106, 1 ≤ Ai ≤ 100

输出

输出这N天结束能够获得的最大利润。

样例输入
5
1 2 3 4 5
样例输出
10

这个题目只要维护最高点就可以了,

相当于其他天都在买,等到最高点卖就行了

我把数组开小了,真是让人愁人

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],b[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i]+b[i-1];
    }
    b[n+1]=-1;
    int s=0;
    for(int i=n; i>0; i--)
    {
        b[i]=max(b[i+1],a[i]);
        s+=b[i]-a[i];
    }
    printf("%d",s);
    return 0;
}

题目3 : 小Hi的生成树计数

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi最近对生成树(包含所有顶点的联通无环子图。)非常的感兴趣,他想知道对于特定的简单平面无向图是不是存在求生成树个数的简单方法。

小Hi定义了这样的图:一个以{0,1,2……n}为顶点的图,顶点0与其他n个顶点直接相连,对于顶点i(1 ≤ i < n),顶点i与顶点i+1连有一条边。下面是小Hi画的图n=4的图:

hiho[Offer收割]编程练习赛30

请求出对于任意n,这样的图的生成树个数。

输入

多组数据,每组数据一行,包括一个整数n

30%的数据(1 ≤ n ≤ 100),组数不超过10组

70%的数据(1 ≤ n ≤ 1000000),组数不超过10组

100%的数据(1 ≤ n ≤ 1000000000),组数不超过10组

输出

每组数据输出一个行包括一个整数,代表了图的生成树个数(对1000000007取模)。

样例输入
2
样例输出
3

找规律的题,不,其实是让你找到状态转移方程的

f[i][0]表示第i个点选择完毕,其连通性为0的方案数
则f[i+1][0]=f[i][0](i+1只与i有边,拯救了i的连通性,却没解决自己的)
+f[i][1](i+1没有边连)
f[i+1][1]=f[i][1]*2(i+1与i连边,或者与0连边,解决了自己的连通性)
+f[i][0]

an=2*an-1+an-2+……+a1+a0

a1=1,a0=1

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL A[2][2], B[2][2], C[2][2], n;
const LL MD = 1e9+7;
struct MX
{
    int v[2][2];
    void O()
    {
        memset(v,0,sizeof(v));
    }
    void E()
    {
        memset(v,0,sizeof(v));
        for (int i = 0; i < 2; ++i)
            v[i][i] = 1;
    }
    MX operator * (const MX &b) const
    {
        MX c;
        c.O();
        for (int k = 0; k < 2; ++k)
        {
            for (int i = 0; i < 2; ++i)
                if (v[i][k])
                {
                    for (int j = 0; j < 2; ++j)
                    {
                        c.v[i][j] = (c.v[i][j] + (LL)v[i][k] * b.v[k][j]) % MD;
                    }
                }
        }
        return c;
    }
    MX operator ^ (LL p) const
    {
        MX y;
        y.E();
        MX x;
        memcpy(x.v, v, sizeof(v));
        while (p)
        {
            if (p & 1)y = y * x;
            x = x * x;
            p >>= 1;
        }
        return y;
    }
} a, b, c;
int main()
{
    a.O();
    a.v[0][0] = 1;
    a.v[0][1] = 1;
    b.O();
    b.v[0][0] = 1;
    b.v[0][1] = 1;
    b.v[1][0] = 1;
    b.v[1][1] = 2;
    LL n;
    while (cin>>n)
    {
        cout<<(a * (b ^ (n - 1))).v[0][1]<<endl;
    }
    return 0;
}

按照3*3的矩阵也能做

hiho[Offer收割]编程练习赛30