2022牛客寒假算法基础集训营1(蒻蒻补题)

这篇博客探讨了动态规划在解决数论问题和区间更新查询中的应用,包括欧拉函数的计算、区间最值维护和逆元计算。同时介绍了如何使用线段树和前缀和等数据结构高效处理区间操作,以及在字符串处理和图形路径优化中的应用。
摘要由CSDN通过智能技术生成

A

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
vector<int> a((int)2e6);
signed main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        int num = a[i];
        int sum = 0;
        while (1)
        {
            while (num)
            {
                sum += num % 10;
                num /= 10;
            }
            if (sum < 10)
                break;
            num = sum;
            sum = 0;
        }
        a[i] = sum;
    }
    int ans[11] = {0};
    ans[0] = 1;
    for (int i = 0; i < n; i++)
    {
        vector<int> ve(11, 0);
        for (int j = 0; j <= 9; j++)
        {
            int u = a[i] + j;
            if (u>9) u = u%10+u/10;
            ve[u] = ans[j];
            ve[u] %= mod;
        }
        ve[a[i]]++;
        for (int j = 0; j <= 9; j++)
        {
            ans[j] += ve[j];
            ans[j] %= mod;
        }
    }
    for (int i = 1; i <= 9; i++)
    {
        cout << ans[i] << " ";
    }
}

B

st表的应用,st[k][i][j]表示从k初始值,i位置开始的2的j次方值
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
int st[3][N][33];
char ch[N]; 
int n, q;
int mod(int x)
{
    return (x % 3 + 3) % 3;
}
int main()
{
    cin >> n >> q;
    scanf("%s", ch + 1);
    for (int j = 0; j <= 20; j++)
    {
        for (int i = 1; i <= n; i++)
        {
            if (j == 0)
            {
                if (ch[i] == 'W')
                {
                    st[0][i][j] = st[1][i][j] = st[2][i][j] = 1;
                }
                if (ch[i] == 'L')
                {
                    st[0][i][j] = 0;
                    st[2][i][j] = st[1][i][j] = -1;
                }
                if (ch[i] == 'D')
                {
                    st[0][i][j] = st[1][i][j] = st[2][i][j] = 0;
                }
            }
            else
            {
                int p1 = i, p2 = i + (1 << (j - 1));
                if (p2 > n)
                {
                    st[0][p1][j] = st[0][p1][j - 1];
                    st[1][p1][j] = st[1][p1][j - 1];
                    st[2][p1][j] = st[2][p1][j - 1];
                }
                else
                {
                    st[0][p1][j] = st[0][p1][j - 1] + st[mod(0 + st[0][p1][j - 1])][p2][j - 1];
                    st[1][p1][j] = st[1][p1][j - 1] + st[mod(1 + st[1][p1][j - 1])][p2][j - 1];
                    st[2][p1][j] = st[2][p1][j - 1] + st[mod(2 + st[2][p1][j - 1])][p2][j - 1];
                }
            }
        }
    }
    int l, r, ans;
    for (int i = 0; i < q; i++)
    {
        scanf("%d%d%d", &l, &r, &ans);
        int pos = l;
        while (pos <= r)
        {
            int j = 0;
            while (pos + (1 << j) - 1 <= r)
                j++;
            j--;
            ans += st[ans % 3][pos][j];
            pos += (1 << j);
        }
        printf("%d\n", ans);
    }
    return 0;
}

C

#include <bits/stdc++.h>
using namespace std;
unordered_map<int,int>mp;
vector<pair<int,int> >ve;
int main()
{
    int n,x;
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=3;j++)
        {
            cin>>x;
            if (x==1)
            {
                ve.push_back({i-j,i});
            }
        }
    }
    sort(ve.begin(),ve.end());
    int m = ve.size();
    int res = 0;
    for (int i=m-1;i>=0;i--)
    {
        int a = ve[i].first;
        int b = ve[i].second;
        int cou = 0;
        int ncou = max(0,4-(b-a));
        for (int j=a;j<b;j++)
        {
            cou+=mp[j];
        }
        if (cou<ncou)
        {
            mp[a] += ncou-cou;
            res+=ncou-cou;
        }
    }
    cout<<res<<endl;
}

D

欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示。特殊的,φ(1)=1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41};
ll n,t;
inline bool isP(int x){
    if(x<=3)    return true;
    for(int i=2;i*i<=n;i++){
        if(n%i==0)    return false;
    }
    return true;
}
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        assert(n!=0);
        ll now=1,i=1;
        if(n==1){
            puts("-1");
            continue;
        }
        while(now*prime[i]<=n){
            now*=prime[i];
            i++;
        }
        printf("%lld ",now);
        while(!isP(n)){
            n--;
        }
        printf("%lld\n",n);
    }
    return 0;
}

E

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        if (m==1)
        {
            if (n==1) cout<<1<<endl;
            else cout<<-1<<endl;
        }
        else 
        {
            int res = 1;
            int cou = 0;
            n-=m;
            m--;
            if (n%m) cou++;
            cou+=n/m;
            res = res+cou*2;
            cout<<res<<endl;
        }
    }
}

F

#include <bits/stdc++.h>
using namespace std;
vector<int> a((int)2e6), sum((int)2e6, 0);
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        stack<int> q;
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
            if (a[i] < m)
                a[i] = -1;
            else
                a[i] = 1;
            sum[i] = a[i] + sum[i - 1];
        }
        int ff = 1;
        int res = 0;
        for (int i = 1; i <= n; i++)
        {
            res += a[i];
            if (res > 0)
            {
                q.push(res);
                res = 0;
            }
            else
            {
                while (!q.empty())
                {
                    int sum = q.top();
                    q.pop();
                    res += sum;
                    if (res > 0)
                    {
                        q.push(res);
                        res = 0;
                        break;
                    }
                }
            }
        }
        if (q.empty()) cout<<-1<<endl;
        else cout<<q.size()<<endl;
    }
}

G

map模拟区间
在这个区间里变换不会促成条件成立
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
int a[N];

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        map<int, int> mp;
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        int ans = 0;
        for (int i = 2; i < n; i++)
        {
            if (a[i] < a[i + 1] && a[i] < a[i - 1])
            {
                ans++;
                int mn = min(a[i - 1], a[i + 1]);
                mp[(a[i] + mn + 1) / 2]++;
            }
            else if (a[i] > a[i + 1] && a[i] > a[i - 1])
            {
                int mx = max(a[i + 1], a[i - 1]);
                mp[(a[i] + mx) / 2 + 1]--;
            }
            else if (a[i] > a[i + 1] && a[i] < a[i - 1])
            {
                mp[(a[i] + a[i + 1]) / 2 + 1]--;
                mp[(a[i] + a[i - 1] + 1) / 2]++;
            }
            else if (a[i] > a[i - 1] && a[i] < a[i + 1])
            {
                mp[(a[i] + a[i - 1]) / 2 + 1]--;
                mp[(a[i] + a[i + 1] + 1) / 2]++;
            }
        }
        int now = 0, mx = 0;
        for (auto it : mp) //遍历
        {
            now += it.second;
            mx = max(now, mx);
        }
        cout << ans - mx << endl;
    }
}

H

#include<bits/stdc++.h>
using namespace std;
vector<int>a((int)2e6);
vector<int>sum1((int)2e6,0),sum2((int)2e6,0);
int main()
{
    int n;
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i]-=500;
    }
    sort(a.begin()+1,a.begin()+n+1);
    for (int i = 1;i<=n;i++)
    {
        sum1[i] = sum1[i-1]+a[i];
    }
    for (int i=n;i>=1;i--)
    {
        sum2[i] = sum2[i+1]+a[i];
    }
    long long res = 0;
    for (int i=1;i<=n;i++)
    {
        int k = lower_bound(a.begin()+i,a.begin()+n+1,-a[i])-a.begin();
        if (k!=i) res+=abs(sum1[k-1]-sum1[i-1]+a[i]*(k-i));
        if (k<=n) res+=abs(sum2[k]+a[i]*(n-k+1));
    }
    cout<<res<<endl;
}

I

一道逆元问题
乘法逆元
Mod为质数时
a/b(mod) = a*b[m-2]
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int mod = 1e9 + 7;
int ksm(int a, int b)
{
    int ans = 1;
    for (; b; b >>= (int)1)
    {
        if (b & 1)
            ans = ans * a % mod;
        a = a * a % mod;
    }
    return ans;
}
int inv(int x)
{
    return ksm(x,mod-2);
}
signed main()
{
    int t,n,m;
    cin>>t;
    while (t--)
    {
        cin>>n>>m;
        int k = ksm(2,n);
        cout<<(((m*((k-2+mod)%mod))%mod)*inv(k))%mod<<endl;
    }
}

J

#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> a((int)2e6);
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int A, B, n;
        cin >> A >> B >> n;
        for (int i = 1; i <= A + B; ++i)
        {
            cin >> a[i].first;
            if (i <= A)
                a[i].second = 1; //安静
            else
                a[i].second = 0; //闹腾
        }
        int ff = 1;
        int cou2 = min(n / 2, B);
        sort(a.begin() + 1, a.begin() + 1 + A + B);
        int res = 0;
        int cou = 0;
        for (int i = A + B; i >= 1; i--)
        {
            if (a[i].second == 1)
            {
                res += a[i].first;
                cou++;
            }
            else
            {
                if (cou2 > 0)
                {
                    res += a[i].first;
                    cou++;
                    cou2--;
                }
            }
            if (cou==n) break;
        }
        if (cou==n) cout<<res<<endl;
        else cout<<-1<<endl;
    }
}

K

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define pb push_back
#define SZ(v) ((int)v.size())
#define fs first
#define sc second
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
int n;
// 0G 1B 2R
int dp[100010][27];
const int inf=-1e6;
char s[100010];
int cnt(int x){
    int g=(x%3==0)+(x/3%3==0)+(x/9%3==0);
    int r=(x%3==2)+(x/3%3==2)+(x/9%3==2);
    return g-r;
}
int main(){
    scanf("%d%s",&n,s+1);
    rep(i,0,n+5){
        rep(j,0,26)    dp[i][j]=inf;
    }
    rep(j,0,26){
        if(s[3]=='G'&&cnt(j)<=0)    continue;
        if(s[3]=='B'&&cnt(j)!=0)    continue;
        if(s[3]=='R'&&cnt(j)>=0)    continue;
        dp[3][j]=(j%3==0)+(j/3%3==0)+(j/9%3==0);
    }
    rep(i,4,n){
        rep(j,0,26){
            if(s[i]=='G'&&cnt(j)<=0)    continue;
            if(s[i]=='B'&&cnt(j)!=0)    continue;
            if(s[i]=='R'&&cnt(j)>=0)    continue;
            rep(k,0,26){
                if(k%3==j/3%3&&k/3%3==j/9%3){
                    dp[i][j]=max(dp[i][j],dp[i-1][k]+(j%3==0));
                }
            }
        }
    }
    int ans=inf;
    rep(j,0,26)    ans=max(ans,dp[n][j]);
    if(ans<0)    puts("-1");
    else    printf("%d\n",ans);
    return 0;
}

L

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        char ch[1010];
        cin>>ch+1;
        double x = 0.0,y = 0.0;
        double res = 0.0;
        for (int i=1;i<=n;i++)
        {
            if (ch[i]=='U')
            {
                y+=1.0;
            }
            else if (ch[i]=='D')
            {
                y-=1.0;
            }
            else if(ch[i]=='L')
            {
                x-=1.0;
            }
            else if (ch[i]=='R')
            {
                x+=1.0;
            }
            res = max(res,x*x+y*y);
        }
        res = sqrt(res);
        printf("%.12lf\n",res);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值