您的位置:首页 > 其它

ACM训练周末总结—11月5日

2017-11-05 19:24 281 查看
        这个半周除了做题以外又重新回顾一下知识点,感觉自己有点掌握的太不扎实。

        先总结一下题目吧。

        N题:给出n个数,从中挑出m个使这m个数相加后可以被d整除。

 这道题在再三思考下确定这道题是用dp做,但对于dp的具体做法我很惭愧没有想对,题目思路给我的启发比较大。       设dp[i][j][k]表示前 i 个数选 j 个被 d 除余 k 。这样dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k-a[i]%d+d];

((a+b)%c=(a%c+b%c)%c),因为(sum+a[i])%d=k推得sum+a[i]=n*d+k,得sum=n*d+k-a[i]得sum%d=(n*d+k-a[i])%d,

得sum%d=(0+k-a[i]%d)%d。这时有一个大坑,为避免k-a[i]%d是负数所以sum%d=(k-a[i]%d+d)。这种对dp的设法比我想的要好,还必须多学习,果然自己太菜了。

        F题:其实就是裸中国剩余定理。给出p,e,i,求一个数x,(x%23)=p,(x%28)=i,(x%33)=e,求满足条件的最小x,其实关于中国剩余定理这位大佬讲的很不错http://www.cnblogs.com/freinds/p/6388992.html

其实这道题还有另一种解法

因为n%3=2, n%5=3, n%7=2 且 3,5,7互质 (互质可以直接得到这三个数的最小公倍数)

令x= n%3=2 , y= n%5=3 ,z= n%7=2

       使5×7×a被3除余1,有35×2=70,即a=2; 

       使3×7×b被5除余1,用21×1=21,即b=1; 

       使3×5×c被7除余1,用15×1=15,即c=1。 

那么n =(70×x+21×y+15×z)%lcm(3,5,7) = 23 这是n的最小解

其实都是一个道理,关于更深一层的,为什么是令其求全部余1的情况下计算,我还得明天拜访下数学老师,至少要得到这么做的证明。

 中国剩余定理的标准解法

#include<bits/stdc++.h>

using namespace std;

#define ll long long

//扩展欧几里得算法 

void gcd(ll a,ll b,ll &d,ll &x,ll &y)

{

    if(b==0){

        d=a;

        x=1,y=0;

    }

    else{//else不能省略 

        gcd(b,a%b,d,y,x);

        y-=(a/b)*x;

    }

}

//中国剩余定理 

ll China(int n,ll *m,ll *a)

{

    ll M=1,d,y,x=0;

    for(int i=0;i<n;i++) M*=m[i];

    for(int i=0;i<n;i++)

    {

        ll w=M/m[i];

        gcd(m[i],w,d,d,y);

        x=(x+y*w*a[i])%M;

    }

    return (x+M)%M;

}

ll m[15],a[15];

int main()

{

    int n;

    scanf("%d",&n);

    for(int i=0;i<n;i++)

        scanf("%lld%lld",&m[i],&a[i]);

    printf("%lld",China(n,m,a));



感觉还要多回顾一下,感觉还漏了不少东西。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: