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));
}
感觉还要多回顾一下,感觉还漏了不少东西。。。
先总结一下题目吧。
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));
}
感觉还要多回顾一下,感觉还漏了不少东西。。。
相关文章推荐
- ACM训练周末总结—11月19日
- ACM训练周末总结—10月15日
- ACM-11月5日周日周末训练心得
- ACM训练周末总结—10月29日
- ACM训练周末总结—11月12日
- ACM训练周末总结—11月26日
- ACM训练周末总结—12月3日
- ACM训练周末总结—9月3日
- ACM训练周末总结—10月8日
- ACM训练半周总结—11月2日
- 山东省第七届ACM大学生程序设计竞赛 训练总结 [8/12] 待补
- 周末训练笔记+2017 ACM/ICPC Asia Regional Qingdao+Xian Online(9.17)
- ACM周末总结—10月22日
- ACM暑期训练总结
- 山东省第八届ACM大学生程序设计竞赛 训练总结 [8/11] 待补
- 2015 ACM-ICPC China Shanghai Metropolitan Programming Contest训练总结【6/10】
- ACM周末总结—9月24日
- 2017开学训练第十周周末总结
- ACM训练半周总结—12月14日
- ACM-9月17日周日周末训练心得