zoukankan      html  css  js  c++  java
  • 2018.09.09 DL24 Day2总结

    今天挂的有点惨……

    T1.forging

    这道题自己在考试的时候想出来了……

    这题是一个期望递推。我们首先考虑这么一件事,一枚硬币,你抛到正面停止,抛到反面继续抛,问期望抛的次数。是两次。我们假设期望抛x次,因为期望对于后面没有影响,所以有如下方程:

    x = 0.5 × 0 + 0.5 × x + 1,x = 2.

    那么我们就可以通过当前合成的概率知道合成的期望次数了。然后一次合成我们需要一把i级的武器,我们只需要1把i-2级的武器和期望次数把的i-1级的武器,所以我们就可以这样递推计算,然后结束。

    结果一是因为自己智障的在两个0级刀合成的时候忘记取max,加上自己空间开的过大,100变0分可还行。

    看下std……自己改完的代码好像丢了……

    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int p=998244353;
    const int N=1e7+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    int inv[N],b[N],c[N],f[N];
    inline int sub(int x,int y){
        x-=y;if(x<0)x+=p;return x;
    }
    int main(){
        freopen("forging.in","r",stdin);freopen("forging.out","w",stdout);
        inv[1]=1;
        for(int i=2;i<N;i++)inv[i]=(ll)(p-p/i)*inv[p%i]%p;
        
        int n=read();f[0]=read();
        int bx=read(),by=read(),cx=read(),cy=read(),mod=read();
        b[0]=by+1;c[0]=cy+1;
        for(int i=1;i<n;i++){
        b[i]=((ll)b[i-1]*bx+by)%mod+1;
        c[i]=((ll)c[i-1]*cx+cy)%mod+1;
        }
        f[1]=(ll)((ll)c[0]*inv[min(b[0],c[0])]%p+1)*f[0]%p;
        for(int i=2;i<=n;i++)
        f[i]=((ll)c[i-1]*inv[min(b[i-2],c[i-1])]%p*f[i-1]%p+f[i-2])%p;
        printf("%d
    ",f[n]);
        return 0;
    }

    T2.division

    这道题当时做的时候没想出来什么……于是好像写了个暴力骗了20。

    后来学姐说是CRT……?没大听懂,copy一下题解……

    std:

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    using namespace std;
    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;
    }
    template<class T>
    void out(T x)
    {
        if(x < 0)
        {
            putchar('-');
            x = -x;
        }
        if(x >= 10)
        {
            out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int id;
    int a[20005],tot,prime[20005];
    bool nonprime[20005];
    int mul(int a,int b,int MOD)
    {
        return 1LL * a * b % MOD;
    }
    int fpow(int x,int c,int MOD)
    {
        int res = 1,t = x;
        while(c)
        {
            if(c & 1) res = res * t % MOD;
            t = t * t % MOD;
            c >>= 1;
        }
        return res;
    }
    int Calc(int p,int m)
    {
        memset(nonprime,0,sizeof(nonprime));
        tot = 0;
        a[1] = 1;
        a[p] = 0;
        for(int i = 2 ; i < p ; ++i)
        {
            if(!nonprime[i])
            {
                a[i] = fpow(i,m,p);
                prime[++tot] = i;
            }
            for(int j = 1 ; j <= tot ; ++j)
            {
                if(i * prime[j] > 10000) break;
                a[i * prime[j]] = a[i] * a[prime[j]] % p;
                nonprime[i * prime[j]] = 1;
                if(i % prime[j] == 0) break;
            }
        }
        int res = 0;
        for(int i = 1 ; i <= p ; ++i)
        {
            int t = a[i] - i + p;
            if(t >= p) t -= p;
            res += (t == 0);
        }
        return res;
    }
    void Solve()
    {
        int ans = 1;
        int c,m;
        read(c);
        read(m);
        int p = 0;
        for(int i = 1 ; i <= c ; ++i)
        {
            read(p);
            ans = mul(ans,Calc(p,m),998244353);
        }
        out(ans);
        enter;
    }
    int main()
    {
        freopen("division.in","r",stdin);
        freopen("division.out","w",stdout);
        read(id);
        int T;
        read(T);
        while(T--) Solve();
    }

    T3.money

    这道题仍然是不会的状态……考试的时候骗到了10分。

    正解是用倍增求出链上最小值,然后合并的时候启发式合并,用倍增记一下边的方向(???)

    表示还是不懂……看一下std吧orz

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cassert>
    #define space putchar(' ')
    #define enter putchar('
    ')
    typedef long long ll;
    using namespace std;
    template <class T>
    void read(T &x){
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x){
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    const int N = 100005, INF = 0x3f3f3f3f;
    int n, m, lastans;
    int ecnt, nxt[2*N], go[2*N], adj[N], edir[2*N], emi[2*N];
    int sze[N], bel[N], dep[N];
    int anc[N][20], mi[N][20], dir[N][20];
    
    void out(){
        for(int i = 1; i <= n; i++)
            for(int j = 0; anc[i][j]; j++)
                printf("anc[%d][%d] = %d, dir = %d, mi = %d
    ", i, j, anc[i][j], dir[i][j], mi[i][j]);
    }
    
    void adde(int u, int v, int d, int w){
        go[++ecnt] = v;
        nxt[ecnt] = adj[u];
        adj[u] = ecnt;
        edir[ecnt] = d;
        emi[ecnt] = w;
    }
    void dfs(int u, int pre, int rt){
        bel[u] = rt;
        dep[u] = dep[pre] + 1;
        for(int i = 0; i < 19; i++){
            anc[u][i + 1] = anc[anc[u][i]][i];
            mi[u][i + 1] = min(mi[u][i], mi[anc[u][i]][i]);
            dir[u][i + 1] = dir[u][i] | dir[anc[u][i]][i];
        }
        for(int e = adj[u], v; e; e = nxt[e])
            if((v = go[e]) != pre){
                anc[v][0] = u;
                mi[v][0] = emi[e];
                dir[v][0] = edir[e] ^ 3;
                dfs(v, u, rt);
            }
    }
    void add(int u, int v, int w){
        adde(u, v, 1, w);
        adde(v, u, 2, w);
        int d = sze[bel[u]] > sze[bel[v]] ? 2 : 1;
        if(d == 2) swap(u, v);
        anc[u][0] = v, mi[u][0] = w, dir[u][0] = d;
        sze[bel[v]] += sze[bel[u]];
        dfs(u, v, bel[v]);
    }
    int query(int u, int v){
        if(bel[u] != bel[v]) return 0;
        int d = 3, ret = INF;
        if(dep[u] > dep[v])
            swap(u, v), d = 0;
        for(int i = 19; i >= 0; i--)
            if(dep[v] - (1 << i) >= dep[u]){
                if(dir[v][i] != (1 ^ d)) return 0;
                ret = min(ret, mi[v][i]);
                v = anc[v][i];
            }
        if(u == v) return ret;
        for(int i = 19; i >= 0; i--)
            if(anc[u][i] != anc[v][i]){
                if(dir[v][i] != (1 ^ d) || dir[u][i] != (2 ^ d)) return 0;
                ret = min(ret, min(mi[v][i], mi[u][i]));
                u = anc[u][i];
                v = anc[v][i];
            }
        if(dir[v][0] != (1 ^ d) || dir[u][0] != (2 ^ d)) return 0;
        ret = min(ret, min(mi[v][0], mi[u][0]));
        return ret;
    }
    
    int main(){
        freopen("money.in", "r", stdin);
        freopen("money.out", "w", stdout);
        read(n), read(m);
        for(int i = 1; i <= n; i++)
            bel[i] = i, sze[i] = 1;
        int op, a, b, c;
        while(m--){
            read(op), read(a), read(b);
            a = (a + lastans) % n + 1;
            b = (b + lastans) % n + 1;
            if(op == 0) read(c), c = (c + lastans) % n + 1, add(a, b, c);
            else write(lastans = query(a, b)), enter;
        }
    
        return 0;
    }
  • 相关阅读:
    【从0安装】mysql
    Java面试题整理(待完善)
    Linux部署Java项目
    执行旧命令的几种方法
    SQL Server死锁报错分析
    枚举类中枚举值不存在.valueOf(enum) 抛异常处理
    InitializingBean的项目开发使用
    巧用枚举来干掉if-else,代码更优雅!
    使用Docker安装配置GitLab CE
    批量条件导出之---CSV
  • 原文地址:https://www.cnblogs.com/captain1/p/9752661.html
Copyright © 2011-2022 走看看