题解
Sample Input
def six 6
def abc 1
def bcd 0
sub bcd abc
add abc six
def universe 0
mul abc six
add universe abc
div bcd six
mod bcd abc
Sample Output
six = 6
abc = 1
bcd = 0
bcd = 140737488355327
abc = 7
universe = 0
abc = 42
universe = 42
bcd = 23456248059221
bcd = 5
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const LL mod=0x00007fffffffffff;//这里比较妙啊有木有
map<string,LL>mp;
int main(){
#ifdef _DEBUG
freopen("data.in","r",stdin);
#endif // _DEBUG
ios::sync_with_stdio(false);
string op,var1,var2;
LL x;
while(cin>>op>>var1){
if(op=="def"){cin>>x;mp[var1]=x;}
else{
cin>>var2;
if(op=="add"){mp[var1]=(mp[var1]+mp[var2])&mod;}//用&代替%效率更高
else if(op=="sub"){mp[var1]=mp[var1]-mp[var2];while(mp[var1]<0)mp[var1]+=mod+1;mp[var1]&mod;}//注意是 +mod+1
else if(op=="mul"){mp[var1]=(mp[var1]*mp[var2])&mod;}
else if(op=="div"){mp[var1]/=mp[var2];}
else if(op=="mod"){mp[var1]%=mp[var2];}
}
cout<<var1<<" = "<<mp[var1]<<endl;
}
return 0;
}
其实这里我没有考虑到long long溢出,幸好数据没有卡,但是很多人都写了快速乘。
快速乘 参考链接
a*b
快速乘法的基本思想 ,是二进制和乘法分配律的结合,(浮点数不满足结合律),
比如,
13==(1101)2
13
==
(
1101
)
2
,
4∗13
4
∗
13
等于
4∗(1101)2
4
∗
(
1101
)
2
,用分配律展开得到
4∗13==4∗(1000+100+1)2
4
∗
13
==
4
∗
(
1000
+
100
+
1
)
2
,
不难观察出,快速幂可以通过判断当前的位(bit)是1还是0,推断出是否需要做求和操作,每次移动到下一位(bit)时,就对ans进行*2操作,等待是否求和。由于除以2和位移操作是等效的,因此这也可以看作是二分思想的应用,这种算法将b进行二分从而减少了不必要的运算,时间复杂度是log(n)。
当两个数相乘可能超过long long 范围的时候用,因为在加法运算的时候不会超,而且可以直接取模,这样就会保证数据超不了了
LL qmul(LL a,LL b,LL mod){
LL ans=0;
for(;b;b>>=1,a=(a<<1)%mod)
if(b&1)ans=(ans+a)%mod;
return ans;
}
LL qpow(LL base,LL n,LL mod){
LL ans=1;
for(;n;n>>=1,base=qmul(base,base,mod)){
if(n&1) ans=qmul(ans,base,mod);
}
return ans;
}
HDU-5187 快速幂+快速乘
Input
Multiply test cases(less than 1000). Seek EOF as the end of the file.
For each case, there are two integers n and p separated by a space in a line. (
1≤n,p≤1018
1
≤
n
,
p
≤
10
18
)
Output
For each test case, output a single line indicating the answer.
Sample Input
2 233
3 5
Sample Output
2
1
code
/**
求解2^n-2 mod p, 1≤n,p≤10^18
两个数相乘可能超过long long,而加法的时候不会超
*/
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
LL qmul(LL a,LL b,LL mod){
LL ans=0;
for(;b;b>>=1,a=(a<<1)%mod)
if(b&1)ans=(ans+a)%mod;
return ans;
}
LL qpow(LL base,LL n,LL mod){
LL ans=1;
for(;n;n>>=1,base=qmul(base,base,mod)){//不能直接乘
if(n&1) ans=qmul(ans,base,mod);
}
return ans;
}
int main(){
#ifdef _DEBUG
freopen("data.in","r",stdin);
#endif // _DEBUG
ios::sync_with_stdio(false);
LL n,p;
while(cin>>n>>p){
if(n==1) {cout<<1%p<<endl;continue;}
cout<<(qpow(2,n,p)-2+p)%p<<endl;//这一步注意,不要为负数
}
return 0;
}
O(1)快速乘
注意有误差。
inline long long multi(long long x,long long y,long long mod)
{
long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
return tmp<0 ? tmp+mod : tmp;
}
inline ll ksc(ll x,ll y,ll mod)
{
return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;
}