zoukankan      html  css  js  c++  java
  • 【NOI OL #1】最小环

    题目链接

    我们来研究一下这个隔着一定距离形成的回路。设起点为$i$,距离为$k$,走了$t$步第一次回到$i$,即在$0sim n-1$编号内,有

    $$egin{matrix} i+t imes k&equiv&i(mod n)\ t imes k&equiv&0(mod n) end{matrix}$$

    又因为$t$最小,所以有$t imes k=p imes n=mathop{lcm}(k,n)$,所以

    $$egin{matrix}t&=&dfrac{operatorname{lcm}(k,n)}{k}\ &=&dfrac{k imes n}{gcd(k,n) imes k}\ &=&dfrac{n}{gcd(k,n)}end{matrix}$$

    也就是说,当设定距离为$k$时,会产生$gcd(k,n)$个长度为$dfrac{n}{gcd(k,n)}$的环。

    然后我们尝试向这些环中填入数字,使得这些环内连续相乘的乘积的和最大。

    首先考虑指定某个环内的数字$a_1sim a_n$,什么填法使得$a_1a_2+a_2a_3+a_3a_4+dots +a_{n-1}a_n+a_na+1$最大。

    首先想到,从最大的数开始,依次贴着写下来,也即$a_1>a_2>a_n>a_3>a_n-1>a_4>dots$

    来证明一波:

    当$n=1,2,3$时不管怎样填都是一样的,命题也成立。(专业术语好像是叫做“命题是平凡的”?)

    若当$n=k$时命题成立,则当$n=k+1$时,插入一个最大的数$a_0$,插入在哪里会使得乘积和最大?

    当我们将$a_0$插入在$a_1a_2$之间时,乘积和增长了$a_0a_1+a_0a_2-a_1a_2$。

    当我们将$a_0$插入在$a_xa_y$之间时,乘积和增长了$a_0a_x+a_0a_y-a_xa_y$。

    接下来证明$a_0a_1+a_0a_2-a_1a_2ge a_0a_x+a_0a_y-a_xa_y$。

    首先移项得到$a_0(a_1+a_2-a_x-a_y)ge a_1a_2-a_xa_y$。

    然后等式左边$ge a_1(a_1+a_2-a_x-a_y)=a_1a_1+a_1a_2-a_1a_x-a_1a_y$。

    于是只要$a_1a_1+a_1a_2-a_1a_x-a_1a_yge a_1a_2-a_xa_y$成立,就会有原不等式成立。

    这里移项,发现$a_1a_1+a_xa_yge a_1a_x+a_1a_y$可以用排序不等式证明。于是原不等式成立。

    所以当$n=k+1$时命题成立,也即对所有正整数$n$,命题都成立。归纳证明完毕。

    然后就是分组的问题了。这个挺显然的直接从大到小分过去。

    证明……思考一下,微扰法?也就是随便抽两个不同组的位置换一下,发现整体和会变小,说明换不得……这个证明是对的吗?

    或者是换个思路:

    $$2(sum a_i^2 -sum a_ia_j)=sum(a_i-a_j)^2$$

    也即“连续乘积和最大”$longrightarrow$“相邻差平方和最小”

    然后也很显然是每次取连续的一段放进同一个环里,而且为了不产生断层,从最大的数开始取。这个也证不动了。算了,放弃了。

    最后,考虑预处理出所有可能的$gcd(n,k)$的情况,也所有就是小于$n/2$的约数。约数的规模是$d(n)$的(总之比$sqrt{n}$小),比询问数小多了。

    注意运算爆int的问题,然后特判一下$k=0$的情况

    代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define IL inline
    #define RG register
    #define _1 first
    #define _2 second
    using namespace std;
    typedef long long LL;
    const int N=2e5;
    
        int n,m;
        LL a[N+3],ans[N+3];
        
    IL void init(){
        sort(a+1,a+n+1,greater<int>());
        memset(ans,0,sizeof ans);
        for(int i=1;i<=n;i++)
            ans[0]+=a[i]*a[i];
        
    }
    
    IL int gcd(int a,int b){
        if(a<b)    swap(a,b);
        int r=a%b;
        while(r>0){
            a=b;    b=r;    r=a%b;
        }
        return b;
        
    }
        
    IL void sol(){
        int k;    scanf("%lld",&k);
        
        if(k==0){
            printf("%lld
    ",ans[k]);    return ;
        }
        
        k=gcd(n,k);
        if(ans[k]!=0){
            printf("%lld
    ",ans[k]);    return ;
        }
        
        int p=n/k;
        ans[k]=0;
        for(int i=0;i<k;i++){
            int s=i*p;
            ans[k]+=a[s+1]*a[s+2];
            for(int j=1;j+2<=p;j+=2)
                ans[k]+=a[s+j]*a[s+j+2];
            for(int j=2;j+2<=p;j+=2)
                ans[k]+=a[s+j]*a[s+j+2];
            ans[k]+=a[s+p-1]*a[s+p];
            
        }
        
        printf("%lld
    ",ans[k]);
        
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
            
        init();
            
        while(m--)
            sol();
    
        return 0;
    
    }
    View Code
  • 相关阅读:
    left join
    order by 对null的处理
    checkbox不显示,试试去掉-webkit-appearance这个样式
    浅谈ES6的let和const的异同点
    ES6中箭头函数的作用
    HTML页面每次打开的时候都清除页面缓存
    解决HTML加载时,外部js文件引用较多,影响页面打开速度问题
    JQuery和Zepto的差异(部分)
    vue-router 快速入门
    vue-resource插件使用
  • 原文地址:https://www.cnblogs.com/Hansue/p/12987827.html
Copyright © 2011-2022 走看看