[补题]省赛训练赛

[补题]省赛训练赛

但我不想认输....

调酒壶里的酸奶

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

最多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\n",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\n", maxx);
    printf("%d %d\n", 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\n",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}^q\phi(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) \]

猜你喜欢

转载自www.cnblogs.com/smallocean/p/10661023.html
今日推荐