• [补题]2019省赛训练赛


    [补题]2019省赛训练赛

    但我不想认输....

    调酒壶里的酸奶

    这道题刚开始想歪了,一直在推公式?其实就是一个简单的记忆化搜索

    最多100*100个状态 求最短路所以BFS

    #include <bits/stdc++.h>
     
    using namespace std;
    int a,b,c;
    struct node{
        int x,y;
        int step;
    }st,en;
    bool vis[105][105];
    int bfs(){
        queue<node>que;
        st.x=0,st.y=0;
        st.step=0;
        que.push(st);
        while(!que.empty()){
            st=que.front();
            que.pop();
            if(st.x==c||st.y==c){
                return st.step;
            }
            vis[st.x][st.y]=1;
            if(!vis[0][st.y]){
                en.x=0;
                en.y=st.y;
                en.step=st.step+1;
                que.push(en);
            }
            if(!vis[st.x][0]){
                en.x=st.x;
                en.y=0;
                en.step=st.step+1;
                que.push(en);
            }
            if(st.x+st.y>=b){
                en.x=st.x-(b-st.y);
                en.y=b;
                if(!vis[en.x][b]) {
                    en.step = st.step + 1;
                    que.push(en);
                }
            }else{
                if(!vis[0][st.x+st.y]){
                    en.x=0;
                    en.y=st.x+st.y;
                    en.step = st.step + 1;
                    que.push(en);
                }
            }
            if(st.x+st.y>=a){
                en.y=st.y-(a-st.x);
                en.x=a;
                if(!vis[a][en.y]) {
                    en.step = st.step + 1;
                    que.push(en);
                }
            }else{
                if(!vis[st.x+st.y][0]){
                    en.y=0;
                    en.x=st.x+st.y;
                    en.step = st.step + 1;
                    que.push(en);
                }
            }
            if(!vis[a][st.y]){
                en.x=a;
                en.y=st.y;
                en.step = st.step + 1;
                que.push(en);
            }
            if(!vis[st.x][b]){
                en.x=st.x;
                en.y=b;
                en.step = st.step + 1;
                que.push(en);
            }
        }
        return -1;
    }
    int main(){
        while(scanf("%d%d%d",&a,&b,&c)!=EOF){
            memset(vis,0,sizeof(vis));
            int ans=bfs();
            if(ans==-1){
                puts("impossible");
            }else{
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

    fps游戏

    高中数学题类型的?通过边的关系求出弧度制的角,然后*180 这题可能卡精度 除法可能有问题 所以需要一个个加

    #include<bits/stdc++.h>
     
    using namespace std;
    const double pi = acos(-1);
     
    int main() {
        int d, r, c;
        double a;
        scanf("%d%d%d%lf", &d, &r, &c, &a);
        double tmp = atan(1.0 * r / d);
        tmp = tmp / pi * 180;
        int k=0;
        double t=0;
        while(k<=c&&t<=tmp){
            t+=a;
            k++;
        }
        printf("%d",max(0,c-k));
        return 0;
    } 
    

    小C的数学问题

    区间价值为区间和乘上区间内的最小值

    用单调栈 每个点对答案的贡献

    右边是到第一个比其小的数的前一个

    维护一个单调栈 当栈顶大于这个数 就把栈顶弹出 同时将弹出的块右边修正 而新加入的数就将左边更新

    然后前缀和搞一搞就可以了

    #include<bits/stdc++.h>
     
    #define ll long long
    using namespace std;
    const int maxn = 1e5 + 7;
    struct node {
        ll v;
        int st, ed;
    } s[maxn];
    int q[maxn];
    ll sum[maxn];
     
    template<class T>
    void read(T &res) {
        res = 0;
        char c = getchar();
        T f = 1;
        while (c < '0' || c > '9') {
            if (c == '-') f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
     
    int main() {
     
        int n;
        read(n);
        for (register int i = 1; i <= n; ++i) {
            read(s[i].v);
            s[i].st = s[i].ed = i;
            sum[i] = sum[i - 1] + s[i].v;
        }
        int tail = 0;
        for (int i = 1; i <= n; ++i) {
            if (tail == 0) {
                q[tail++] = i;
            } else {
                if (s[i].v >= s[q[tail - 1]].v) {
                    q[tail++] = i;
                } else {
                    while (tail != 0 && s[i].v < s[q[tail - 1]].v) {
                        s[i].st = s[q[tail - 1]].st;
                        s[q[tail - 1]].ed = i - 1;
                        tail--;
                    }
                    q[tail++] = i;
                }
            }
        }
        while (tail != 0) {
            s[q[tail - 1]].ed = n;
            tail--;
        }
        int l = 0, r = 0;
        ll maxx = -1;
        for (register int i = n; i >= 1; --i) {
            if ((sum[s[i].ed] - sum[s[i].st - 1]) * s[i].v > maxx) {
                maxx = (sum[s[i].ed] - sum[s[i].st - 1]) * s[i].v;
                l = s[i].st, r = s[i].ed;
            }
        }
        printf("%lld
    ", maxx);
        printf("%d %d
    ", l, r);
     
        return 0;
    }
    

    Master of Phi

    数学问题 公式好好写应该能做出来

    最后就是求一个:

    [sum_{d|n}n*prod_{p|n}(1-1/p) ]

    其中d就是n的因子 而p是n的质因子

    原文中给出了质因子和质因子的个数

    (2^2 3^2​)

    [ans=(1-1/2)(1-1/3)*4 ]

    最后全部加起来乘以n

    dfs 组合型枚举

    #include<bits/stdc++.h>
     
    #define ll long long
    using namespace std;
    const int maxn = 30;
    const int mod = 998244353;
    ll qpow(ll k,int n){
        ll res=1;
        while(n){
            if(n&1) res=res*k%mod;
            k=k*k%mod;
            n>>=1;
        }
        return res;
    }
    ll q[maxn];
    ll p[maxn],ans,inv[maxn];
    int m;
    template<class T>
    void read(T &res) {
        res = 0;
        char c = getchar();
        T f = 1;
        while (c < '0' || c > '9') {
            if (c == '-') f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
    void dfs(int cnt,ll num){
        if(cnt==m+1){
            ans=(ans+num)%mod;
            return;
        }
        dfs(cnt+1,num);
        dfs(cnt+1,(p[cnt]-1)*num%mod*q[cnt]%mod*inv[cnt]%mod);
    }
    int main() {
        int T,n;read(T);
        while(T--){
            read(m);
            n=1;
            ans=0;
            for(int i=1;i<=m;++i){
                read(p[i]);
                read(q[i]);
                inv[i]=qpow(p[i]%mod,mod-2);
                n=n*qpow(p[i],q[i])%mod;
            }
            dfs(1,1);
            printf("%lld
    ",ans*n%mod);
        }
        return 0;
    }
    

    这个也有纯数学的方法

    题目是求狄利克雷函数 而且是积性函数 所以他们的狄利克雷卷积也是积性函数

    具体思想是推出每个(p^q)的狄利克雷卷积的式子 带进去然后乘起来

    [设n=p^q ]

    [sum_{d|n}phi(d)frac{n}{d}=phi(1)*p^q+sum_{i=1}^qphi(p^i)frac{p^q}{p^i} ]

    [=p^q+p^q(1-frac{1}{p})sum_{i=1}^q1 ]

    [=p^q+p^{q-1}q(p-1) ]

    [=p^{q-1}(p+pq-q) ]

    Cosmetic Survey

    题意几个概念弄懂其实不是很难:

    最后主要问题转化为:

    1.路径上最短的边是这个路径的权值

    2.(s[u][v])的值是u到v所有路径权值的最大值

    然后SPFA的松弛操作为:

    [d[s][v]=max(min(d[s][v],val),d[s][v]) ]

    #include <iostream>
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int N=505,M=505*505;
    int he[N],ver[M],edge[M],nex[M],s[N];
    int n,m,tot;
    queue<int> q;
    bool vis[N];
    int a[N];
    int d[N][N];
    int ent[N][N];
    vector<int> ant;
    void add(int u,int v,int w)
    {
        ver[++tot]=v;
        edge[tot]=w;
        nex[tot]=he[u];
        he[u] = tot;
    }
    void spfa(int st)
    {
        memset(s,0,sizeof s);
        memset(vis,0,sizeof vis);
        s[st]=0;
        vis[st]=1;
        q.push(st);
        s[st]=0x3f3f3f3f;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            vis[x]=0;
            for(int i=he[x];i;i=nex[i]){
                int y=ver[i];
                int z=edge[i];
                if(s[y]<min(s[x],z)){
                    s[y]=min(s[x],z);
                    if(!vis[y]){
                        q.push(y);
                        vis[y]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        while(m--){
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                if(a[i]==0)
                    a[i]=1e9;
            }
            for(int i=1;i<=n-1;i++)
            {
                for(int j=i+1;j<=n;j++)
                {
                    if(a[i]<a[j])
                        d[i][j]++;
                    else if(a[i]>a[j])
                        d[j][i]++;
                }
            }
        }
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(j!=i){
                    if(d[i][j]>d[j][i])
                    {
                        add(i,j,d[i][j]);
                    }
                    else if(d[j][i]>d[i][j])
                    {
                        add(j,i,d[j][i]);
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            spfa(i);
            for(int j=1;j<=n;j++)
            {
                if(j!=i)
                    ent[i][j]=s[j];//cout<<s[j]<<endl;
            }
        }
        for(int i=1;i<=n;i++)
        {
            int f=0;
            for(int j=1;j<=n;j++)
            {
                if(i!=j)
                {
                    if(ent[i][j]<ent[j][i])
                    {
                        f=1;
                        break;
                    }
                }
            }
            if(!f)
            {
                ant.push_back(i);
            }
        }
        for(int i=0;i<ant.size();i++)
        {
            if(i)
                printf(" ");
            printf("%d",ant[i]);
        }
        printf("
    ");
        return 0;
    }
    
    

    T-net

    挺绕的一个贪心

    #include <bits/stdc++.h>
    
    #define ll long long
    using namespace std;
    const int N = 1e5 + 10;
    int s[N];
    int d[N];
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n, a, b;
        ll ans = 0;
        cin >> n >> a >> b;
        for (int i = 1; i <= n; ++i) {
            cin >> s[i];
        }
        sort(s + 1, s + 1 + n);
        if (a > b) swap(a, b);
        s[0] = s[1], s[n + 1] = s[n];
        for (int i = 1; i <= n; ++i) {
            if (d[i] == a) continue;
            if (d[i] != b) {
                if (s[i] - s[i - 1] <= a && s[i + 1] - s[i] <= a) {
                    d[i] = a;
                    continue;
                }
                if (s[i] - s[i - 1] > b || s[i + 1] - s[i] > b) {
                    cout << -1 << endl;
                    return 0;
                }
            }
            d[i] = b;
            int j = i;
            while (s[i] + b >= s[j] && j <= n) ++j;
            --j;
            //判断 d[j]需不需要用b
            bool flag = 0;
            for (int k = i + 1; k < j; ++k) {
                if (s[k] - s[k - 1] > a || s[k + 1] - s[k] > a) {
                    flag = 1;
                    break;
                }
            }
            if (!flag) continue;
            else d[j] = b;
    
            for (int r = j - 1; r > i; --r) {// 将右边相差a但左边相差b的变成a
                if (d[r]) break;
                if (s[r + 1] - s[r] <= a) {
                    d[r] = a;
                } else break;
            }
            for (int l = i + 1; l < j; ++l) {// 将左边相差a但右边相差b的变成a
                if (d[l]) break;
                if (s[l] - s[l - 1] <= a) {
                    d[l] = a;
                } else break;
            }
        }
        for (int i = 1; i <= n; ++i) {
            ans += d[i];
        }
        cout << ans << endl;
        return 0;
    }
    
    /* 原先写法 虽然相邻的会优但没有处理左边a右边b或者右边a左边b的情况
     * if(a[i]-a[i-1]<=x&&a[i+1]-a[i]<=x)
                    ans+=x;
                else if(a[i]-a[i-1]<=y&&a[i+1]-a[i]<=y)
                    ans+=y;
     */
    

    LED

    二分误差 然后check

    check时只要尽量满足就行

    v的只用就是排序

    先是第一部分 当l大于误差的时候break

    这个时候是L1灯的第一个

    维护一个最大和最小的区间 每次更新

    当前的灯的最大值小于之前的最小值 直接返回false

    当前的灯的最小值大于之前的最大值那么就是到L2区间了 后面同理

    #include <bits/stdc++.h>
    
    #define ll long long
    using namespace std;
    const int maxn = 3e5 + 7;
    struct node {
        int v;
        double l;
    } s[maxn];
    int n;
    
    bool check(double p) {
        int i;
        for (i = 1; i <= n; ++i) {
            if (s[i].l > p) {
                break;
            }
        }
        if (i > n) return true;
        double minn = s[i].l - p, maxx = s[i].l + p;
        ++i;
        for (; i <= n; ++i) {
            if (s[i].l + p < minn) {
                return false;
            }
            if (s[i].l - p <= maxx) {
                minn = max(s[i].l - p, minn);
                maxx = min(s[i].l + p, maxx);
            } else if (s[i].l - p > maxx) {
                break;
            }
        }
        if (i > n)return true;
        minn = s[i].l - p, maxx = s[i].l + p;
        for (; i <= n; ++i) {
            if (s[i].l + p < minn) {
                return false;
            }
            if (s[i].l - p <= maxx) {
                minn = max(s[i].l - p, minn);
                maxx = min(s[i].l + p, maxx);
            } else if (s[i].l - p > maxx) {
                return false;
            }
        }
        return true;
    }
    
    bool cmp(node a, node b) {
        return a.v < b.v;
    }
    
    int main() {
        scanf("%d", &n);
        double ans = 0;
        for (int i = 1; i <= n; ++i) {
            scanf("%d%lf", &s[i].v, &s[i].l);
            if (s[i].v == 0) ans = max(ans, s[i].l);
        }
        sort(s + 1, s + 1 + n, cmp);
        double l = 0, r = 1e15;
        while (l + 1e-5 < r) {
            double mid = (l + r) / 2;
            if (check(mid)) {
                r = mid;
            } else l = mid;
        }
        printf("%.1f
    ", max(l, ans));
        return 0;
    }
    
    
    
    不要忘记努力,不要辜负自己 欢迎指正 QQ:1468580561
  • 相关阅读:
    How to Set up Cplex Dev Environment under Linux
    矿大linux下拨号上网的一个方法——利用NetworkManager
    4月4日在写协议分析器中遇到的问题:对类指针的直接赋值中遇到的问题
    新篇章的开始
    纠结N久,还是开通了博客园,希望跟大家多多交流吧
    SQL去重distinct方法解析
    接口测试基础知识介绍
    Appium是什么
    appium环境配置
    appium操作
  • 原文地址:https://www.cnblogs.com/smallocean/p/10661023.html
Copyright © 2020-2023  润新知