zoukankan      html  css  js  c++  java
  • 8.7 Round 1

    今天思维性差了一点,但是我的失误变得贼多...

    T1:https://www.luogu.org/problem/T92371

    失误:我 竟然 没看见 多组数据

    爆零彻底

    找规律题,答案是n * phi[n] / 2

    证明:

    集合{[0,n-1]中存在逆元的数}==集合{[0,n-1]中存在逆元的数的逆元}

    gcd(n,i)=gcd(n,n-i);

    所以与n互质的数可以关于n/2对称的,也就是相加等于n;

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<climits>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    using namespace std;
    #define O(x) cout << #x << " " << x << endl;
    #define B cout << "breakpoint" << endl;
    #define clr(a) memset(a,0,sizeof(a));
    typedef int mainint;
    #define int long long
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    int n;
    const int maxn = 2e5 + 5;
    int p[maxn],cnt;
    bool vis[maxn];
    void init(int n)
    {
        for(int i = 2;i <= n;i++)
        {
            if(!vis[i]) p[++cnt] = i;
            for(int j = 1;j <= cnt && i * p[j] <= n;j++)
            {
                vis[i * p[j]] = 1;
                if(i % p[j] == 0) break;
            }
        }
    }
    int gcd(int a,int b) { return !b ? a :gcd(b,a % b); }
    mainint main()
    {
        freopen("zip.in","r",stdin);
        freopen("zip.out","w",stdout);
        int t = read();
        while(t--)
        {
        int n = read();
        int N = maxn - 5;
        init(N);
        int tot = 1,tp = n;
        for(int i = 2;i <= sqrt(n);i++)
        {
                if(tp % i == 0) tp /= i,tot *= (i - 1);
                while(tp % i == 0) tp /= i,tot *= i;
        }
        if(tp != 1) tot *= (tp - 1);
        printf("%lld
    ",tot * n / 2);
        }
        return 0;
    }
        
             
    View Code

    T2:https://www.luogu.org/problem/T92372

    失误:处理第二问时,我直接向下dfs,这样复杂度会炸

    1,3问略

    第二问:记录F[u][0]/[1]:u不选/选,除u及其子树以外的点的最小花费

    转移:

    F[u][0] = F[fa][1] + f[fa] - min(f[u],g[u]);
    F[u][1] = min(F[u][0],F[fa][0] + g[fa] - f[u]);

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<climits>
    #include<map>
    #include<queue>
    #include<vector>
    using namespace std;
    #define O(x) cout << #x << " " << x << endl;
    #define B cout << "breakpoint" << endl;
    #define clr(a) memset(a,0,sizeof(a));
    typedef long long ll;
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    const int maxn = 1e5 + 5;
    const ll mod = 5462617;
    int f[maxn],g[maxn],n;
    ll cntf[maxn],cntg[maxn];
    struct egde
    {
        int to,next;
    }e[maxn << 1];
    int fir[maxn],alloc;
    void adde(int u,int v)
    {
        e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v;
        swap(u,v);
        e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v;
    }
    void dfs(int u,int fa)
    {
        f[u] = 1,g[u] = 0;
        cntf[u] = cntg[u] = 1ll;
        for(int i = fir[u];i;i = e[i].next)
        {
            int v = e[i].to;
            if(v == fa) continue;
            dfs(v,u);
            f[u] += min(f[v],g[v]);
            if(f[v] < g[v]) (cntf[u] *= cntf[v]) %= mod;
            else if(f[v] > g[v]) (cntf[u] *= cntg[v]) %= mod;
            else cntf[u] = cntf[u] * ((cntf[v] + cntg[v]) % mod) % mod;
            g[u] += f[v],(cntg[u] *= cntf[v]) %= mod;
        }
    }
    bool not_in[maxn];
    int F[maxn][2];//0:x不选 1:x选  除x及其子树以外的最大价值 
    void deal(int u,int fa)
    {
        if(u != 1)
        { 
            F[u][0] = F[fa][1] + f[fa] - min(f[u],g[u]);
            F[u][1] = min(F[u][0],F[fa][0] + g[fa] - f[u]);
        }
        for(int i = fir[u];i;i = e[i].next)
        {
            int v = e[i].to;
            if(v == fa) continue;
            deal(v,u);
        }
    }
    int main()
    {
        freopen("rainbow.in","r",stdin);
        freopen("rainbow.out","w",stdout);
        n = read();
        for(int i = 1;i < n;i++)
        {
            int u = read(),v = read();
            adde(u,v);
        }
        dfs(1,0);
        int ans = min(f[1],g[1]);
        printf("%d
    ",ans);
        for(int i = 1;i <= n;i++) not_in[i] = 1;
        deal(1,0);
        int cnt = 0;
        for(int i = 1;i <= n;i++) if(F[i][1] + f[i] != ans) cnt++;
        printf("%d
    ",cnt);
        if(f[1] > g[1]) printf("%lld",cntg[1]); 
        else if(f[1] < g[1]) printf("%lld",cntf[1]);
        else printf("%lld",(cntf[1] + cntg[1]) % mod);
        return 0;
    }
    /*
    5
    1 2
    1 3
    2 4
    2 5
    */
    View Code

    T3:https://www.luogu.org/problem/T92373

    失误:二分时存在可能没有LCP的情况,所以要l=0,r = min(len[x],len[y])

    二分+哈希

    基数记得选>5e5的

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<climits>
    #include<map>
    #include<queue>
    #include<vector>
    using namespace std;
    #define O(x) cout << #x << " " << x << endl;
    #define B cout << "breakpoint" << endl;
    #define clr(a) memset(a,0,sizeof(a));
    typedef int mainint;
    #define int long long
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    const int mod1 = 1e9 + 7;
    const int mod2 = 998244353;
    const int b1 = 5e5 + 9;
    const int b2 = 5e5 + 29;
    const int maxn = 1e5 + 5;
    vector<int> hs1[maxn],hs2[maxn];
    vector<int> tp[maxn];
    int t[maxn * 5],cnt;
    int n,m,len[maxn],x,y;
    inline bool check(int s)
    {
        return hs1[x][s - 1] == hs1[y][s - 1] && hs2[x][s - 1] == hs2[y][s - 1];
    }
    main()
    {
        freopen("girls.in","r",stdin);
        freopen("girls.out","w",stdout);
        n = read(),m = read();
        for(int i = 1;i <= n;i++)
        {
            len[i] = read();
            for(int j = 1;j <= len[i];j++)
            {
                int x = read();
                tp[i].push_back(x);
                t[++cnt] = x;
            }
        }
        sort(t + 1,t + 1 + cnt);
        int tot = unique(t + 1,t + 1 + cnt) - t - 1;
        for(int i = 1;i <= n;i++)
        {
            for(int j = 0;j < len[i];j++)
            {
                tp[i][j] = lower_bound(t + 1,t + 1 + tot,tp[i][j]) - t + 1;
                if(j) hs1[i].push_back((hs1[i][j - 1] * b1 % mod1 + tp[i][j]) % mod1),
                        hs2[i].push_back((hs2[i][j - 1] * b2 % mod2 + tp[i][j]) % mod2);
                else hs1[i].push_back(tp[i][j]),hs2[i].push_back(tp[i][j]);
            }
        }
        while(m--)
        {
            x = read(),y = read();
            int l = 0,r = min(len[x],len[y]);
            bool flag = 0;
            while(l < r)
            {
                int mid = (l + r + 1) >> 1;
                if(check(mid)) l = mid,flag = 1;
                else r = mid - 1;
            }
            printf("%lld
    ",l);
        }
    }
    /*
    3 3
    3 1 2 3
    3 1 2 4
    5 1 2 3 4 5
    1 3
    2 1
    2 3
    */        
    View Code

    自以为能够AK结果死的很惨。。。

    以后要更小心,看题面,多考虑情况,自以为对的题也要对拍一下

  • 相关阅读:
    vijos 1426
    2455 繁忙的都市
    2104 删除物品
    3235 战争
    BZOJ 2962
    COGS 265 线段覆盖
    P2184 贪婪大陆
    0729模拟赛解题报告
    BZOJ 1012
    BZOJ 2763
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/11315109.html
Copyright © 2011-2022 走看看