“科大讯飞杯”第十七届同济大学程序设计预选赛暨高校网络友谊赛

给出的仅为我的做题顺序,与题目难度不一定匹配

F、排列计算

前缀和
给定区间,可以控制区间元素加1,最后把区间元素的染色次数排序,从次数最大开始填最大的数。
具体区间元素+1,又不用模拟去实现,直接在左端点处加1,右端点后面一个点减1即可。最后求前缀和就行。
再把求好的前缀和数组排个序,大功告成

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef long long ll;
#define INF 0x3f3f3f3f
const int mod = 1e9+7;
const int maxn = 8000*8000+5;
#define iss ios::sync_with_stdio(false)
inline ll read(){
    ll s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

ll num[200005];

int main(){
    int n = read(),m = read();
    while(m--){
        int l = read(),r = read();
        num[l]++;
        num[r+1]--;
    }
    for(int i = 0 ; i <= n ; ++i ) num[i]+=num[i-1];
    sort(num+1,num+1+n);
    ll ans = 0;
    for(int i = 1 ; i <= n ;++i){
        ans += (i*num[i]);
    }
    cout<<ans<<endl;
}

B、伤害计算

图片说明 写法,用了个图片说明和异常处理。对输入的字符串进行一个个数据处理即可,注意最后判断整数精度别开太小
)我竟然被1e-6坑了一发……
当然还有更好的写法,直接乘个2去算,最后判奇偶就行了。

import math
a = list(input().split('+'))
ans = 0.0
for i in a:
    try:
        tmp = int(i)
        ans += tmp
    except:
        cnt,tmp = map(int,i.split('d'))
        ans += cnt*(tmp+1)*0.5
if ans-int(ans)>0.1:
    print(ans)
else :
    ans=int(ans)
    print(ans)

A、张老师和菜哭武的游戏

前导知识:拓展欧里几得
我们知道对于图片说明 存在整数解x与y,需要gcd(a,b)是c的因子。
对于用a和b求解出来的数随意组合也符合上面的图片说明
那么这题,给出了a,b,直接求解gcd即可,用n除掉gcd就是可以拿走的数。在对这个数判断奇偶即可

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;

inline int read() {
    int s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

int main() {
    int T = read();
    while (T--) {
        int n = read(), a = read(), b = read();
        int tmp = __gcd(a, b);
        if (tmp != 1) n /= tmp;
        if (n & 1)    puts("Yes");
        else    puts("No");
    }
    return 0;
}

D、车辆调度

地图很小,车辆很少,直接暴力破解即可。
直接跑地图即可,再把每个位置上下左右都走一遍
(钟涛大佬tql)

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef long long ll;
#define INF 0x3f3f3f3f
const int mod = 1e9 + 7;
const int maxn = 8000 * 8000 + 5;
#define iss ios::sync_with_stdio(false)
inline ll read() {
    ll s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
int w, h, kk;
char Map[15][15];
bool dfs(int x) {
    if (x > kk) return false;
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            if (Map[i][j] == 'R') {
                Map[i][j] = '.';
                int k;
                if (i > 0 && Map[i - 1][j] == '.' || Map[i - 1][j] == 'D') {
                    for (int k = i - 1; k >= 0; k--)
                        if (k == 0 || Map[k - 1][j] == 'R' || Map[k - 1][j] == 'X') {
                            if (Map[k][j] == 'D') return true;
                            Map[k][j] = 'R';
                            if (dfs(x + 1)) return true;
                            Map[k][j] = '.';
                            break;
                        }
                }
                if (i + 1 < h && Map[i + 1][j] == '.' || Map[i + 1][j] == 'D') {
                    for (int k = i + 1; k < h; ++k) {
                        if (k == h - 1 || Map[k + 1][j] == 'R' || Map[k + 1][j] == 'X') {
                            if (Map[k][j] == 'D') return true;
                            Map[k][j] = 'R';
                            if (dfs(x + 1)) return true;
                            Map[k][j] = '.';
                            break;
                        }
                    }
                }
                if (j + 1 < w && Map[i][j + 1] == '.' || Map[i][j + 1] == 'D') {
                    for (int k = j + 1; k < w; ++k) {
                        if (k == w - 1 || Map[i][k + 1] == 'R' || Map[i][k + 1] == 'X') {
                            if (Map[i][k] == 'D') return true;
                            Map[i][k] = 'R';
                            if (dfs(x + 1)) return true;
                            Map[i][k] = '.';
                            break;
                        }
                    }
                }
                if (j > 0 && Map[i][j - 1] == '.' || Map[i][j - 1] == 'D') {
                    for (int k = j - 1; k >= 0; k--)
                        if (k == 0 || Map[i][k - 1] == 'R' || Map[i][k - 1] == 'X') {
                            if (Map[i][k] == 'D') return true;
                            Map[i][k] = 'R';
                            if (dfs(x + 1)) return true;
                            Map[i][k] = '.';
                            break;
                        }
                }
                Map[i][j] = 'R';
            }
        }
    }
    return false;
}
int main() {
    w = read(), h = read(), kk = read();
    for (int i = 0; i < h; ++i)
        scanf("%s", Map[i]);
    if (dfs(1)) puts("YES");
    else puts("NO");
}

好了下面是比赛时间未写出来的了

E、弦

分子式卡特兰数我看出来了……居然死在了分母手上,我一直以为分母是个末项(n * 2 - 1)的等差数列……我一直只连接2条线。
现在发现是多蠢。分母应该是图片说明
再结合卡特兰数的通项公式图片说明
约分化简得到答案等于图片说明 在处理一下阶乘数组,利用费马小定理求解乘法逆元就是答案了。

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;

inline int read() {
    int s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

const int MOD = 1e9 + 7;
const int N = 1e7 + 7;
ll jc[N];

ll qpow(ll a, ll b) {
    ll ans = 1;
    while (b) {
        if (b & 1)  (ans *= a) %= MOD;
        b >>= 1;
        (a *= a) %= MOD;
    }
    return ans;
}

int main() {
    int n = read();
    jc[0] = 1;
    for (int i = 1; i <= n + 1; ++i) jc[i] = jc[i - 1] * i % MOD;
    printf("%lld\n", qpow(2,n) * qpow(jc[n + 1], MOD - 2) % MOD);
    return 0;
}

F、斐波那契和

我敢保证这题是最憋屈的,以为两天前的牛客练习赛63,斐波那契字符串刚刚好说了一句杜教BM,本菜鸡只百度了一下,知道是个帮你求递推式的没有去记,因为想着有OEIS,如果知道前几项直接求道通项公式就行了……然后结果就是这题没法做。。
具体实现……就是套板子,一般来说求解到前10项左右即可出答案,稳健一点,直接开了10000的数组,全部放进去。算到答案即可。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define pb push_back
typedef long long ll;
#define SZ(x) ((ll)(x).size())
typedef vector<ll> VI;
typedef pair<ll, ll> PII;
const ll mod = 998244353;
ll powmod(ll a, ll b) { ll res = 1; a %= mod; assert(b >= 0); for (; b; b >>= 1) { if (b & 1)res = res * a % mod; a = a * a % mod; }return res; }
// head

ll _, n;
namespace linear_seq {
    const ll N = 10010;
    ll res[N], base[N], _c[N], _md[N];

    vector<ll> Md;
    void mul(ll* a, ll* b, ll k) {
        rep(i, 0, k + k) _c[i] = 0;
        rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod;
        for (ll i = k + k - 1; i >= k; i--) if (_c[i])
            rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
        rep(i, 0, k) a[i] = _c[i];
    }
    ll solve(ll n, VI a, VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
//        printf("%d\n",SZ(b));
        ll ans = 0, pnt = 0;
        ll k = SZ(a);
        assert(SZ(a) == SZ(b));
        rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1;
        Md.clear();
        rep(i, 0, k) if (_md[i] != 0) Md.push_back(i);
        rep(i, 0, k) res[i] = base[i] = 0;
        res[0] = 1;
        while ((1ll << pnt) <= n) pnt++;
        for (ll p = pnt; p >= 0; p--) {
            mul(res, res, k);
            if ((n >> p) & 1) {
                for (ll i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0;
                rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod;
            }
        }
        rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod;
        if (ans < 0) ans += mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1, 1), B(1, 1);
        ll L = 0, m = 1, b = 1;
        rep(n, 0, SZ(s)) {
            ll d = 0;
            rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
            if (d == 0) ++m;
            else if (2 * L <= n) {
                VI T = C;
                ll c = mod - d * powmod(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                L = n + 1 - L; B = T; b = d; m = 1;
            }
            else {
                ll c = mod - d * powmod(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                ++m;
            }
        }
        return C;
    }
    ll gao(VI a, ll n) {
        VI c = BM(a);
        c.erase(c.begin());
        rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod;
        return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
    }
};

inline ll read() {
    ll s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

ll f[10005];

int main() {
    ll n = read(), k = read();
    f[1] = 1, f[2] = 1;
    for (int i = 3; i <= 10000; ++i)
        f[i] = (f[i - 1] + f[i - 2]) % mod;
    VI a;
    ll x = 0;
    for (int i = 1; i <= 10000; ++i) {
        x = (x + powmod(i, k) * f[i] % mod) % mod;
        a.push_back(x);
    }
    printf("%lld\n", linear_seq::gao(a, n - 1));
}
全部评论

相关推荐

醒工硬件:1学校那里把xxxxx学院去了,加了学院看着就不像本校 2简历实习和项目稍微精简一下。字太多,面试官看着累 3第一个实习格式和第二个实习不一样。建议换行 4项目描述太详细了,你快把原理图贴上来了。比如可以这样描述:使用yyyy芯片,使用xx拓扑,使用pwm控制频率与占空比,进行了了mos/电感/变压器选型,实现了xx功能 建议把技术栈和你做的较为有亮点的工作归纳出来 5熟悉正反激这个是真的吗
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务