# 湖北省赛网络赛总结+题解

“深圳计算科研院杯“E起来编程暨第三届湖北省赛

比赛传送门

捏马人给痛没了,DEF思路晚点补!

总结:

现在我还很烂,但是我会努力变厉害的!

题解:

A Warm Welcome

签到题,直接输出就完了。
《能力要平均值·人形翻译机》队友速切。

代码:
#include <bits/stdc++.h>
typedef long long ll;
int main()
{
    std::cout << "Shenzhen Institute of Computing Sciences";
    return 0;
}

B Mr.Maxwell and attractions

贪心。

题目大意:

给你 n , m , t , k n,m,t,k n,m,t,k四个字母, n n n代表有 n n n个户内景点; m m m代表有 m m m个室外景点。然后输入 a a a数组,代表每一个室内景点能带来的愉悦度,然后输入 b b b数组,代表每一个户外景点能带来的愉悦度。有 t t t天,其中 k k k天只能下午出发。
已知:

  1. 户外景点下午出发愉悦度暂时变为80%;
  2. 所有景点重复访问将永久变为上次访问愉悦度的60%(反复叠加)。
思路:

优先队列+贪心。
总之其实是这样,天数循环中分为两个大块,能否早上出发非得下午出发不可
那么处理是这样,能早上出发的情况下为未折扣的户外和户内直接对比大小,如果优先户内了,那么由行动(户内)决定今天什么时候出发(下午),消耗k,让后面有更多选择。
反之折扣后的户外和户内直接对比,因为没得选择了,户外的都加debuff了。

一开始的错误思路:

直接让早上出发和下午出发两种,泾渭分明的两个while。

代码:
#include <bits/stdc++.h>

typedef long long ll;
const int MAXN = 1e5 + 10;
double a[MAXN], b[MAXN];

int main() {
    int n, m, t, k;
    scanf("%d%d%d%d", &n, &m, &t, &k);
    for (int i = 1; i <= n; ++i) scanf("%lf", &a[i]);
    for (int i = 1; i <= m; ++i) scanf("%lf", &b[i]);
    double ans = 0;
    std::priority_queue<double> que1, que2;
    for (int i = 1; i <= n; ++i) que1.push(a[i]);
    for (int i = 1; i <= m; ++i) que2.push(b[i]);
    int tt = t - k;
    for (int i = 1; i <= t; i++) {
        double u = que1.top();
        double v = que2.top();
        que1.pop();
        que2.pop();
        if (i + k <= t) {
            //意思是还能选择早上出发,不用折扣80%
            //就是单纯的比大小,谁大去哪儿。
            if (u > v) {
            //优先去室内,那顺便让这一天变成下午出发,就能消耗k
                ans += u;
                que1.push(u * 0.6);
                que2.push(v);
                k--;
            } else {
                ans += v;
                que1.push(u), que2.push(v * 0.6);
            }
        } else {
        //必须消耗下午出发了
            if (u > v * 0.8) {
                ans += u;
                que1.push(u * 0.6);
                que2.push(v);
            } else {
                ans += 0.8 * v;
                que1.push(u), que2.push(v * 0.6);
            }

        }
    }
    printf("%.2f\n", ans);
}

C Hamster and Equation

两个FOR循环。
F ( x 1 , x 2 ) = K ∗ F ( x 3 , x 4 ) F(x1,x2) = K*F(x3,x4) F(x1,x2)=KF(x3,x4)

代码:
#include <bits/stdc++.h>
typedef long long ll;
const int MAXN = 1e6 + 10, INF = 0x3f3f3f3f;
int st[MAXN];
int main()
{
    int t; scanf("%d", &t);
    while (t--)
    {
        int n, k; scanf("%d%d", &n, &k);
        memset(st, 0, sizeof st);
        int mini = INF, maxi = -INF;
        for (int i = -n; i <= n; ++i)
            for (int j = -n; j <= n; ++j)
            {
                int u = i * (i + 1) + j * (j + 1);
                //循环暴力枚举x1/x2
                st[u]++;
                //记录F(x,y)==u的xy组数
                mini = std::min(mini, u);
                maxi = std::max(maxi, u);
            }
        if (k > 0)
        {
            ll ans = 0;
            for (int i = mini; i <= maxi; ++i)
                if (i % k == 0) ans += 1ll * st[i] * st[i / k];
            printf("%lld\n", ans);
        }
        else if (k < 0)
            printf("%lld\n", 1ll * st[0] * st[0]);
            //负数特判
    }
    return 0;
}
总结教训:

帮忙看错误主要看代码,针对代码。 不能再用玄学bug法了…

D WA

set维护贪心选最小。

代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
const int maxn=1e5+10;
vector<pair<int,int>>a;
int main()               
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n,k;cin>>n>>k;
    string s;cin>>s;
    int id=-1,id1=-1;
    for(int i=0;i<n;i++)
    if(s[i]=='a') {
        if(id==-1) id=i;
        id1=i;
    }
    if(id==-1) {
        for(int i=0;i<k;i++)
        s[i]='a';
        cout<<k-1<<endl<<s<<endl;
        return 0;
    }
    int l=id,r=id;
    for(int i=id+1;i<=id1;i++)
    {
        if(s[i]=='a') {
            r=i;
            a.push_back({r-l-1,l+1});
            l=i;
        }
    }
    sort(a.begin(),a.end());
    for(int i=0;i<a.size();i++)
    {
        if(a[i].first<=k) {
            k-=a[i].first;
            for(int j=a[i].second;j<min(a[i].first+a[i].second,n);j++)
            s[j]='a';
        }
        else {
            for(int j=a[i].second;j<min(a[i].second+k,n);j++)
            s[j]='a';k=0;
        }
    }
    // for(auto i:a)
    // cout<<i.first<<" "<<i.second<<endl;
    if(k) {
        for(int i=id-1;i>=0;i--)
        {
            s[i]='a';k--;
            if(!k) break;
        }
        for(int i=id1+1;i<min(id1+1+k,n);i++)
        {
            s[i]='a';
        }
    }
    int ans=0;
    for(int i=1;i<n;i++)
    if(s[i]=='a'&&s[i-1]=='a') ans++;
    cout<<ans<<endl<<s<<endl;
    return 0;  
}

E Pipeline Maintenance

矩阵树定理+打表除以n2找规律。
队友的200行巨长板子过了。
我只能您。

代码:
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int MOD = 1e9 + 7;
template <class T> class Matrix
{
public:
    int r, c;
    vector < vector <T> > v;
    Matrix()
    {
        r = c = 0;
        v.clear();
    }
    Matrix(int a, int b): r(a), c(b)
    {
        v.resize(r + 1);
        for (int i = 0; i <= r; ++i) v[i].resize(c + 1);
        for (int i = 0; i <= r; ++i)
            for (int j = 0; j <= c; ++j)
                v[i][j] = 0;
    }
    void clear()
    {
        for (int i = 0; i <= r; ++i)
            for (int j = 0; j <= c; ++j)
                v[i][j] = 0;
    }
    vector <T> &operator [](int x) { return v[x]; }
    Matrix <T> &operator +=(Matrix <T>);
    Matrix <T> &operator -=(Matrix <T>);
    Matrix <T> &operator *=(Matrix <T>);
    Matrix <T> &operator %=(int);
};
template <class T> Matrix <T> operator +(Matrix <T> A, Matrix <T> B)//加
{
    if (A.r != B.r || A.c != B.c) throw;
    Matrix <T> C(A.r, A.c);
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            C[i][j] = (A[i][j] % MOD + B[i][j] % MOD) % MOD;
            //!!此处有必要时添加取模:C[i][j] = (A[i][j] % MOD + B[i][j] % MOD) % MOD;!!
    return C;
}
template <class T> Matrix <T> operator -(Matrix <T> A, Matrix <T> B)//减
{
    if (A.r != B.r || A.c != B.c) throw;
    Matrix <T> C(A.r, A.c);
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            C[i][j] = ((A[i][j] % MOD - B[i][j] % MOD) % MOD + MOD) % MOD;
            //!!此处有必要时添加取模(注意负数):C[i][j] = ((A[i][j] % MOD - B[i][j] % MOD) % MOD + MOD) % MOD;!!
    return C;
}
template <class T> Matrix <T> operator *(Matrix <T> A, Matrix <T> B)//乘
{
    if (A.c != B.r) throw;
    Matrix <T> C(A.r, B.c);
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            if (A[i][j])//稀疏矩阵优化
            {
                for (int k = 1; k <= B.c; ++k)
                    C[i][k] = (C[i][k] + (A[i][j] % MOD) * (B[j][k] % MOD)) % MOD;
                    //!!此处有必要时添加取模:C[i][k] = (C[i][k] + (A[i][j] % MOD) * (B[j][k] % MOD)) % MOD;!!
            }
    return C;
}
template <class T> Matrix <T> operator %(Matrix <T> A, int M)//模
{
    Matrix <T> C(A.r, A.c);
    for (int i = 1; i <= C.r; ++i)
        for (int j = 1; j <= C.c; ++j)
            C[i][j] = (A[i][j] % M + M) % M;
    return C;
}
template <class T> Matrix <T> &Matrix <T>::operator +=(Matrix <T> A)//自加
{
    if (A.r != r || A.c != c) throw;
    for (int i = 1; i <= r; ++i)
        for (int j = 1; j <= c; ++j)
            v[i][j] = (v[i][j] % MOD + A[i][j] % MOD) % MOD;
            //!!此处有必要时添加取模:v[i][j] = (v[i][j] % MOD + A[i][j] % MOD) % MOD;!!
    return *this;
}
template <class T> Matrix <T> &Matrix <T>::operator -=(Matrix <T> A)//自减
{
    if (A.r != r || A.c != c) throw;
    for (int i = 1; i <= r; ++i)
        for (int j = 1; j <= c; ++j)
            v[i][j] = ((v[i][j] % MOD - A[i][j] % MOD) % MOD + MOD) % MOD;
            //!!此处有必要时添加取模(注意负数):v[i][j] = ((v[i][j] % MOD - A[i][j] % MOD) % MOD + MOD) % MOD!!
    return *this;
}
template <class T> Matrix <T> &Matrix <T>::operator *=(Matrix <T> B)//自乘
{
    if (c != B.r) throw;
    Matrix <T> C(r, B.c);
    for (int i = 1; i <= r; ++i)
        for (int j = 1; j <= c; ++j)
            if (v[i][j])//稀疏矩阵优化
            {
                for (int k = 1; k <= B.c; ++k)
                    C[i][k] = (C[i][k] + (v[i][j] % MOD) * (B[j][k] % MOD)) % MOD;
                    //!!此处有必要时添加取模:C[i][k] = (C[i][k] + (v[i][j] % MOD) * (B[j][k] % MOD)) % MOD;!!
            }
    c = B.c;
    v.clear(); v.resize(r + 1);
    for (int i = 0; i <= r; ++i) v[i].resize(c + 1);
    for (int i = 0; i <= r; ++i)
        for (int j = 0; j <= c; ++j)
            v[i][j] = C[i][j];
    return *this;
}
template <class T> Matrix <T> &Matrix <T>::operator %=(int M)//自模
{
    for (int i = 1; i <= r; ++i)
        for (int j = 1; j <= c; ++j)
            v[i][j] = ((v[i][j] % M) + M) % M;
    return *this;
}
template <class T> bool operator ==(const Matrix <T> A, const Matrix <T> B)//判断相等
{
    if (A.r != B.r || A.c != B.c) return 0;
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            if (A[i][j] != B[i][j]) return 0;
    return 1;
}
//方阵类
template <class T> class Square: public Matrix <T>
{
public:
    Square(): Matrix <T>() {}
    Square(int n): Matrix <T>(n, n) {}
    Square(int a, int b)
    {
        if (a != b) throw;
        Matrix <T>::r = a, Matrix <T>::c = b;
        Matrix <T>::v.resize(a + 1);
        for (int i = 0; i <= a; ++i) Matrix <T>::v[i].resize(b + 1);
        for (int i = 0; i <= a; ++i)
            for (int j = 0; j <= b; ++j)
                Matrix <T>::v[i][j] = 0;
    }
    Square(Matrix <T> A)
    {
        int mini = min(A.r, A.c);
        Matrix <T>::v.resize(mini + 1);
        Matrix <T>::r = Matrix <T>::c = mini;
        for (int i = 0; i <= mini; ++i) Matrix <T>::v[i].resize(mini + 1);
        for (int i = 1; i <= mini; ++i)
            for (int j = 1; j <= mini; ++j)
                Matrix <T>::v[i][j] = A[i][j];
    }
    operator Matrix <T>()
    {
        Matrix <T> A(Matrix <T>::r, Matrix <T>::c);
        for (int i = 1; i <= Matrix <T>::r; ++i)
            for (int j = 1; j <= Matrix <T>::c; ++j)
                A[i][j] = Matrix <T>::v[i][j];
        return A;
    }
    Square <T> &operator ^=(int);
};
//单位阵可以用A^0获取
template <class T> Square <T> operator ^(Square <T> A, int num)//乘方
{
    int n = A.r;
    Square <T> ans(n);
    for (int i = 1; i <= n; ++i) ans[i][i] = 1;
    while (num)
    {
        if (num & 1) ans = (ans * A) % MOD; //!!此处有必要时添加取模:ans = (ans * A) % MOD;!!
        A = (A * A) % MOD;//!!此处有必要时添加取模:A = (A * A) % MOD;!!
        num >>= 1;
    }
    return ans;
}
template <class T> Square <T> &Square <T>::operator ^=(int num)//乘方
{
    int n = Matrix <T>::r;
    Square <T> ans(n), temp(*this);
    for (int i = 1; i <= n; ++i) ans[i][i] = 1;
    while (num)
    {
        if (num & 1) ans = (ans * temp) % MOD;//!!此处有必要时添加取模:ans = (ans * temp) % MOD;!!
        temp = (temp * temp) % MOD;//!!此处有必要时添加取模:temp = (temp * temp) % MOD;!!
        num >>= 1;
    }
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            Matrix <T>::v[i][j] = ans[i][j];
    return *this;
}
template <class T> Square <T> operator &(Square <T> A, int num)//A^0~A^n求和
{
    Square <T> temp(A.r * 2, A.c * 2);
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            temp[i][j] = A[i][j];
    for (int i = A.c + 1; i <= A.c * 2; ++i) temp[i - A.c][i] = 1;
    for (int i = A.r + 1; i <= A.r * 2; ++i) temp[i][i] = 1;
    temp ^= num + 1;
    Square <T> ans(A.r, A.c);
    for (int i = 1; i <= A.r; ++i)
        for (int j = 1; j <= A.c; ++j)
            ans[i][j] = temp[i][j + A.c];
    return ans;
}
int main()
{
    Square < ll > A(2);
    ll n; scanf("%lld", &n);
    A[1][1] = 5, A[1][2] = -1, A[2][1] = 1, A[2][2] = 0;
    Matrix < ll > p(2, 1);
    p[1][1] = 1, p[2][1] = 0;
    printf("%lld\n", ((A ^ (n - 1)) * p % MOD)[1][1] * n % MOD * n % MOD);
    return 0;
}

F Meet in another world, enjoy tasty food!

差分维护。

题目大意:

排队的人排第几每回合损失耐心度多少,为零就走人了,而且他走了以后后面的人减去的耐心度少一。求最终走人顺序编号。

我题目都喂错了,稳点不要急躁。

代码:
#include <bits/stdc++.h>
typedef long long ll;
const int MAXN = 1e3 + 10;
ll a[MAXN], dif[MAXN], st[MAXN];
std::vector < ll > ans;
ll calc(ll a, ll b)
{
    return a / b + (a % b != 0);
}
int main()
{
    ll n; scanf("%lld", &n);
    for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    for (int i = 1; i <= n; ++i) dif[i] = 1;
    ll s = 0, pp = 1;
    while (pp <= n)
    {
        ll idx = 0, sidx = 0;
        for (int j = 1; j <= n; ++j)
        {
            if (st[j]) continue;
            s += dif[j];
            if (!idx || calc(a[idx], sidx) > calc(a[j], s))
                idx = j, sidx = s;
        }
        s = 0;
        ll k = calc(a[idx], sidx);
        int t = 0;
        for (int j = 1; j <= n; ++j)
        {
            if (st[j]) continue;
            s += dif[j];
            a[j] -= (k - 1) * s + (s - t);
            if (a[j] <= 0)
            {
                ans.push_back(j);
                st[j] = pp++;
                t++;
            }
        }
        s = 0;
    }
    for (int i = 0; i < n; ++i)
        printf("%lld ", ans[i]);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值