[英]I encountered the 10^9+7 problem but I can't understand the relation between the distributive properties of mod and my problem
Given 3 numbers ab c get a^b, b^a, c^x where x is abs diff between b and a cout each one but mod 10^9+7 in ascending order.给定 3 个数字 ab c 得到 a^b、b^a、c^x,其中 x 是 b 和 cout 之间的绝对差异,但按升序 mod 10^9+7。 well I searched web for how to use the distributive property but didn't understand it since I am beginner,好吧,我在 web 上搜索了如何使用分配属性,但因为我是初学者所以不明白,
I use very simple for loops so understanding this problem is a bit hard for me so how can I relate these mod rules with powers too in loops?我使用非常简单的 for 循环,所以理解这个问题对我来说有点困难,所以我如何在循环中将这些 mod 规则与权力联系起来? If anyone can help me I would be so happy.如果有人能帮助我,我会很高兴。 note time limit is 1 second which makes it harder注意时间限制是 1 秒,这使得它更难
I tried to mod the result every time in the loop then times it by the original number.我尝试在循环中每次都修改结果,然后将其乘以原始数字。 for example if 2^3 then 1st loop given variables cin>>a,a would be 2, num =a would be like this a = (a % 10^9 + 7) * num this works for very small inputs but large ones it exceed time例如,如果 2^3 那么第一个循环给定变量 cin>>a,a 将是 2,num =a 将像这样 a = (a % 10^9 + 7) * num 这适用于非常小的输入但大的输入它超过了时间
#include <iostream>
#include <cmath>
using namespace std;
int main ()
{
long long a,b,c,one,two,thr;
long long x;
long long mod = 1e9+7;
cin>>a>>b>>c;
one = a;
two = b;
thr = c;
if (a>=b)
x = a - b;
else
x = b - a;
for(int i = 0; i < b-1;i++)
{
a = ((a % mod) * (one%mod))%mod;
}
for(int j = 0; j < a-1;j++)
{
b = ((b % mod) * (two%mod))%mod;
}
for(int k = 0; k < x-1;k++)
{
c = ((c % mod) * (thr%mod))%mod;
}
}
I use very simple for loops [...] this works for very small inputs, but large ones it exceeds time.我使用非常简单的 for 循环 [...] 这适用于非常小的输入,但大的输入会超过时间。
There is an algorithm called "exponentiation by squaring" that has a logarithmic time complexity, rather then a linear one.有一种称为“平方求幂”的算法,它具有对数时间复杂度,而不是线性时间复杂度。
It works breaking down the power exponent while increasing the base.它可以在增加基数的同时分解幂指数。
Consider, eg x 355 .考虑,例如 x 355 。 Instead of multiplying x 354 times, we can observe that而不是乘以 x 354次,我们可以观察到
x 355 = x·x 354 = x·(x 2 ) 177 = x·x 2 ·(x 2 ) 176 = x·x 2 ·(x 4 ) 88 = x·x 2 ·(x 8 ) 44 = x·x 2 ·(x 16 ) 22 = x·x 2 ·(x 32 ) 11 = x·x 2 ·x 32 ·(x 32 ) 10 = x·x 2 ·x 32 ·(x 64 ) 5 = x·x 2 ·x 32 ·x 64 ·(x 64 ) 4 = x·x 2 ·x 32 ·x 64 ·(x 128 ) 2 = x 1 ·x 2 ·x 32 ·x 64 ·x 256 x 355 = x·x 354 = x·(x 2 ) 177 = x·x 2 ·(x 2 ) 176 = x·x 2 ·(x 4 ) 88 = x·x 2 ·(x 8 ) 44 = x ·x 2 ·(x 16 ) 22 = x·x 2 ·(x 32 ) 11 = x·x 2 ·x 32 ·(x 32 ) 10 = x·x 2 ·x 32 ·(x 64 ) 5 = x ·x 2 ·x 32 ·x 64 ·(x 64 ) 4 = x·x 2 ·x 32 ·x 64 ·(x 128 ) 2 = x 1 ·x 2 ·x 32 ·x 64 ·x 256
That took "only" 12 steps.这“只”走了12步。
To implement it, we only need to be able to perform modular multiplications safely, without overflowing.要实现它,我们只需要能够安全地执行模乘法,而不会溢出。 Given the value of the modulus, a type like std::int64_t
is wide enough.给定模数的值,像std::int64_t
这样的类型就足够宽了。
#include <iostream>
#include <cstdint>
#include <limits>
#include <cassert>
namespace modular
{
auto exponentiation(std::int64_t base, std::int64_t exponent) -> std::int64_t;
}
int main()
{
std::int64_t a, b, c;
std::cin >> a >> b >> c;
auto const x{ b < a ? a - b : b - a };
std::cout << modular::exponentiation(a, b) << '\n'
<< modular::exponentiation(b, a) << '\n'
<< modular::exponentiation(c, x) << '\n';
return 0;
}
namespace modular
{
constexpr std::int64_t M{ 1'000'000'007 };
// We need the mathematical modulo
auto from(std::int64_t x)
{
static_assert(M > 0);
x %= M;
return x < 0 ? x + M : x;
}
// It assumes that both a and b are already mod M
auto multiplication_(std::int64_t a, std::int64_t b)
{
assert( 0 <= a and a < M and 0 <= b and b < M );
assert( b == 0 or a <= std::numeric_limits<int64_t>::max() / b );
return (a * b) % M;
}
// Implements exponentiation by squaring
auto exponentiation(std::int64_t base, std::int64_t exponent) -> std::int64_t
{
assert( exponent >= 0 );
auto b{ from(base) };
std::int64_t x{ 1 };
while ( exponent > 1 )
{
if ( exponent % 2 != 0 )
{
x = multiplication_(x, b);
--exponent;
}
b = multiplication_(b, b);
exponent /= 2;
}
return multiplication_(b, x);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.