整个欢乐赛#69 就这一题有点难度。
想要证明的话需要一些数论知识。
求证:(amodm+bmodm)modm=(a+b)modm(a,b,m 为整数)。
令 a=k1m+amodm,b=k2m+bmodm(k1,k2 为整数),
则 (a+b)modm=(k1m+amodm+k2m+bmodm)modm=(amodm+bmodm)modm。
注意此处 m∣(k1m,k2m)。
求证:(amodm)×(bmodm)modm=a×bmodm(a,b,m 为整数)。
令 a=k1m+amodm,b=k2m+bmodm(k1,k2 为整数),
则 a×bmodm=(k1m+amodm)×(k2m+bmodm)modm=[k1m×k2m+k1m×(bmodm)+(amodm)×k2m+(amodm)×(bmodm)]modm=(amodm)×(bmodm)modm。
注意此处 m∣[k1m×k2m,k1m×(bmodm),(amodm)×k2m]。
根据以上的两个证明,可知边做边取模并不影响计算的结果,所以就有了 40 pts 代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int n,x,y,z;
signed main(){
cin>>n>>x;
while (n--){
cin>>y>>z;
x=max(x+y,x*z);
x%=mod;
}
cout<<x;
return 0;
}
注意到上面加粗的文字,这种做法并不会影响到计算的结果,但会影响到你的选择。
口胡 hack:
上一轮 x 变为 109+7,取模后为 0。
此时 yi=1,zi=2,你的代码会选择 x+yi 操作,使其变为 1。
但实际上 x+yi 操作会使 x 变为 109+8,而 x×zi 操作会使 x 变为 2×109+14,应选择后者。
但这并不意味着你不能边做边取模。
注意到 yi,zi 远小于模数,那么当至少完成一次取模时,若 zi≥2,那么一定选择 x×zi 操作,否则一定选择 x+yi 操作。
好的,100 pts 代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int n,x,y,z;
bool f;
signed main(){
cin>>n>>x;
while (n--){
cin>>y>>z;
if (f){
if (z>1){
x*=z;
}
else {
x+=y;
}
x%=mod;
continue;
}
x=max(x+y,x*z);
if (x>mod){
f=1;
}
x%=mod;
}
cout<<x;
return 0;
}
以上全文共 1781 字符,肝了 40+ min,创作不易,点个赞扒。
有帮助,赞一个