zoukankan      html  css  js  c++  java
  • HGOI 20190519 题解

    脑补了一下今天的比赛难度和之前zju-lzw出的题目画风迥异。

    难度完全不是一个水平的好伐。

    Probem A palindrome 

    给出一个$n$个元素的数组,可以任意指定一个数字$m$让所有$a_i = a_i \% m$。

    使得最终得出的数组成为形如${1,2,3,2,1}$的回文数组,求最大的$m$。

    对于100%的数据$1leq n leq 10^5,1 leq a_i leq 10^9$

    Sol: 我们要求同余方程 $ left{egin{matrix} a_1 equiv a_n (mod m)\ ...\  a_i equiv a_{n-i+1}(mod m)\  ...\ a_n equiv  a_1(mod m)\ end{matrix} ight.$的最大解$m$,

    显然的我们考虑一种普遍的情况$a equiv  b (mod p)$。

    定理:上述结论成立的充分必要条件是$|a-b| equiv 0 (mod p)$

    充分性:设$a leq b$ 那么有 $b-a = kp$即$b = kp + a$显然$a equiv  b (mod p) $

    必要性:证明同理。 所以这两个命题是等价的关系。

    所以我们只要做差求gcd 就可以了。

    # include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    int a[N];
    int gcd(int a,int b)
    {
        if (b==0) return a;
        return gcd(b,a%b); 
    }
    int main()
    {
        int n; scanf("%d",&n); 
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        int ans=0;
        for (int i=1;i<=n/2;i++) ans=gcd(ans,abs(a[n-i+1]-a[i]));
        if (ans==0) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
    palindrome.cpp

    Probem B factorial 

    给出一个序列${a_i}$,完成三种操作:

    1.区间 [l,r] 所有数+1 

    2.询问区间 [l,r] $sumlimits_{i=l}^{r} a_i ! mod 10^9$

    3.单点更新pos,val

    对于100%的数据$n,m leq 10^5 val,a_ileq 10^9$

    Sol: 都9102年了还是有人不知道线段树的骚操作。

    模数是个合数你有什么好说的,一定有鬼。

    发现$40! mod 10^9 = 0$于是我们所有的操作都打上了 $40$次的限制。

    不需要懒标记,直接下放到叶子节点就可以。

    复杂度$O(40 imes n log_2 n)$

    # include <bits/stdc++.h>
    # define int long long
    using namespace std;
    const int N=1e5+10;
    const int mo=1e9;
    int t[N<<2],s[50],g[N<<2],a[N];
    int n,m;
    void build(int x,int l,int r)
    {
        if (l==r) { g[x]=a[l]; g[x]=min(g[x],41ll); t[x]=s[g[x]]; return;}
        int mid=(l+r)/2;
        build(2*x,l,mid);
        build(2*x+1,mid+1,r);
        t[x]=(t[2*x]+t[2*x+1])%mo;
        g[x]=g[2*x]+g[2*x+1];
    }
    void update1(int x,int l,int r,int ql,int qr)
    {
        if (g[x]>=(r-l+1)*41) return;
        if (l==r) { g[x]++; g[x]=min(g[x],41ll); t[x]=s[g[x]]; return;}
        int mid=(l+r)/2;
        if (ql<=mid) update1(2*x,l,mid,ql,qr);
        if (qr>mid) update1(2*x+1,mid+1,r,ql,qr);
        t[x]=(t[2*x]+t[2*x+1])%mo;
        g[x]=g[2*x]+g[2*x+1];
    }
    void update2(int x,int l,int r,int pos,int val)
    {
        if (l==r) { g[x]=val; g[x]=min(g[x],41ll); t[x]=s[g[x]]; return;}
        int mid=(l+r)/2;
        if (pos<=mid) update2(2*x,l,mid,pos,val);
        else update2(2*x+1,mid+1,r,pos,val);
        t[x]=(t[2*x]+t[2*x+1])%mo;
        g[x]=g[2*x]+g[2*x+1];
    }
    int query(int x,int l,int r,int ql,int qr)
    {
        if (ql<=l&&r<=qr) return t[x];
        int mid=(l+r)/2,ret=0;
        if (ql<=mid) ret=(ret+query(2*x,l,mid,ql,qr))%mo;
        if (qr>mid) ret=(ret+query(2*x+1,mid+1,r,ql,qr))%mo;
        return ret;
    }
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        for (int i=1;i<=n;i++) {
            scanf("%lld",&a[i]);    
        }
        s[0]=1; for (int i=1;i<=45;i++) s[i]=s[i-1]*i%mo; s[0]=0;
        build(1,1,n);
        while (m--) {
            int op,l,r;
            scanf("%lld%lld%lld",&op,&l,&r);
            if (op==1) {
                update1(1,1,n,l,r);
            } else if (op==2) {
                printf("%lld
    ",query(1,1,n,l,r));
            } else if (op==3) {
                update2(1,1,n,l,r);
            }
        }
        return 0;
    }
    factorial.cpp

    Problem C triangle

    定义函数$f(x)  = $为一条直角边为$x$的正整数边长直角三角形种类数。 

    给出$q$组询问,每个询问含有一个值$n$ ,询问$f(x) = n$的最小整数解$x_{min}$

    对于100%的数据,$qleq 10^5 , 1leq n leq 10^6$

    Sol : $n^2 +b^2 = c^2 $得出$n^2=(c+b)(c-b)-st(s=c+b,t=c-b)$

    解得$c = frac{s+t}{2} , b = frac{s-t}{2} , t < s$。

    结合三角形是边长是整数,即$b,c in Z$

    所以任意解$(s,t)$可以用$st = n^2,s > t, s equiv t (mod 2)$

    所以我们估计$f(n) = frac{d(n^2)}{2}$规模的 , 手玩一下我们会发现。

    对$n$质因数分解$n = 2^{k_2} imes 3 ^{k_3} imes 5^{k_5} ... $

    所以$n^2 =  2^{2k_2} imes 3 ^{2k_3} imes 5^{2k_5} ...$

    由于$s,t$的奇偶性必须同奇同偶,所以$2k_2$个$2$不能全分给$s,t$减少了一些方案。

    其质因子需要任意分。三角形边长不能为0,所以排除$s=t$的情况,还需-1。

    所以$f(n) = frac{2{k_2}(2{k_3}+1)(2{k_5}+1)...}{2}$ 

    令$f(x) = n$,对于选中的$x$,需要最小,使得$2{k_2}(2{k_3}+1)(2{k_5}+1)... = 2n+1$

    用若干(取个14个就够了)个小素数来组成$m$可以保证m最小,依次考虑每次质数,背包一下就行了。

    复杂度$O(qk^2) , k  =14$

    #include <bits/stdc++.h>
    using namespace std;
    #define N 2000010
    typedef long long LL;
    LL F[N];
    LL temp[N];
    const LL lim = 1e16;
    int p[20] = {14, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 33, 37, 41};
    void up(LL &x, LL y) { if (x == 0) x = y; else x = min(x, y);}
    
    int main()
    {
        F[1] = 1;
        for (int i = 1; i <= p[0]; ++i) {
            memset(temp, 0, sizeof(temp));
            for (int j = 1; j < N; ++j) {
                if (F[j] == 0) continue;
                int kk = 0; LL s = 1;
                while (true) {
                    if (j*(kk*2+1) >= N) break;
                    if (F[j] > lim / s) break;
                    if (i > 1 || kk == 0) up(temp[j*(kk*2+1)], F[j]*s);
                    ++kk;
                    if (s > lim / p[i]) break;
                    s = s * p[i];
                }
            }
            memcpy(F, temp, sizeof(temp));
        }
        int T, n; scanf("%d", &T);
        while (T--) {
            scanf("%d", &n);
            LL ans = lim + 1;
            if (F[2*n+1]) ans = min(ans, F[2*n+1]);
            LL w = 2;
            for (int k = 1; k < 60; ++k, w = w * 2) {
                if ((2*n+1) % (2*k-1)) continue;
                LL t = F[(2*n+1)/(2*k-1)];
                if (t && t <= lim / w) ans = min(ans, t*w);
            }
            if (ans == lim+1) ans = -1;        
            printf("%lld
    ", ans);
        }
        return 0;
    }
    triangle.cpp
  • 相关阅读:
    ajax设置自定义请求头
    tomcat修改端口号
    下载文件(前端+后台)
    ajax请求超时判断(转载)
    js判断变量类型
    js中判断是否包含某个字符串
    Java将json字符串转成map
    Linux上安装设置mysql 5.7.24
    js格式化json字符串和json对象
    bootstrap中的data-toggle模态框相关
  • 原文地址:https://www.cnblogs.com/ljc20020730/p/10890433.html
Copyright © 2011-2022 走看看