题目:The power of Fibonacci
链接:https://ac.nowcoder.com/acm/contest/889/A
大意:给定n<=1e9,m<=1e3求 ( ∑ i = 0 n F i m ) m o d 1 e 9 (\sum_{i=0}^nF_i^m)mod 1e9 (∑i=0nFim)mod1e9
分析:有一个要注意的地方就是取模用的是1e9而不是某个大质数,这是有特殊的用意的。因为根据中国剩余定理,我们可以通过 ( ∑ i = 0 n F i m ) m o d ( 2 9 ) (\sum_{i=0}^nF_i^m)mod (2^9) (∑i=0nFim)mod(29)和 ( ∑ i = 0 n F i m ) m o d ( 5 9 ) (\sum_{i=0}^nF_i^m)mod (5^9) (∑i=0nFim)mod(59)来求 ( ∑ i = 0 n F i m ) m o d 1 e 9 (\sum_{i=0}^nF_i^m)mod 1e9 (∑i=0nFim)mod1e9。 2 9 = 512 , 5 9 = 1953125 2^9=512,5^9=1953125 29=512,59=1953125这样任务就变简单了。另外由于是模空间,所以肯定是有循环节的,根据结论/经验/盲猜,循环节应该是mod周围,比mod不会大多少。于是可以提前算出循环节,再根据循环节快速算出 ( ∑ i = 0 n F i m ) m o d ( 2 9 ) (\sum_{i=0}^nF_i^m)mod (2^9) (∑i=0nFim)mod(29)和 ( ∑ i = 0 n F i m ) m o d ( 5 9 ) (\sum_{i=0}^nF_i^m)mod (5^9) (∑i=0nFim)mod(59)。然后就可以求ans了
#include
using namespace std;
typedef long long ll;
ll n, m;
int f[50000000];
int qpow(ll a, int b, int p)
{
a %= p; ll ret = 1;
while (b)
{
if (b & 1)ret = ret * a%p;
b >>= 1; a = a * a%p;
}
return ret;
}
ll inv(ll a, ll p) { return qpow(a, p - 1, p); }
ll findr(int p)
{
ll ans(0);
f[0] = 0; f[1] = 1;
int i=1;
do
{
++i;
f[i] = f[i - 1] + f[i - 2];
if (f[i] >= p)f[i] -= p;
} while ((f[i - 1] != 0 )||( f[i] != 1));
int len = (i - 2) - 0 + 1;
for (int i = 0; i < len; ++i)
{
ll cnt = n / len; if (i <= (n%len))++cnt;
ans = (1ll * qpow(f[i], m, p)*cnt+ans) %p;
}
return ans;
}
int main()
{
cin >> n >> m;
ll ans2 = findr(512);
ll ans5 = findr(1953125);
ll M = 1e9;
ll m2 = 512, m5 = 1953125;
ll M2 = 1953125, M5 = 512;
//ll t2 = inv(M2, 512), t5 = inv(M5, 1953125);
ll t2 = 0;
while ((t2 * M2 % m2) != 1)
++t2;
ll t5 = 0;
while ((t5 * M5 % m5 )!= 1)
++t5;
ll ans = (ans2*t2%M*M2%M + ans5 * t5%M*M5%M) % M;
cout << ans << endl;
}
题目:Quadratic equation
链接:https://ac.nowcoder.com/acm/contest/889/B
大意: ( x + y ) m o d p = b , ( x × y ) m o d p = c (x+y)modp=b ,(x \times y) \bmod p = c (x+y)modp=b,(x×y)modp=c,输入x,y
分析:简单解一下方程,然后就是二次剩余的板子了。主要是不懂二次剩余
#include
#define F(i,a,b) for(int i=(a);i<=int(b);++i)
using namespace std;
typedef long long ll;
#define MODED(n) ((n)<0?(n)%mod+mod:(n)%mod)
const int inf = 0x3f3f3f3f;
const int maxn = int(20);
const int mod = 1e9 + 7;
mt19937_64 gen(time(0));
struct T { ll x, y; };ll w;
//复数乘法
T mul_two(T a, T b, ll p)
{
T ans;
ans.x = (a.x*b.x%p + a.y*b.y%p*w%p) % p;
ans.y = (a.x*b.y%p + a.y*b.x%p) % p;
return ans;
}
//复数快速幂
T qpow_two(T a, ll n, ll p)
{
T ans = { 1,0 };
while (n)
{
if (n & 1) ans = mul_two(ans, a, p);
n >>= 1; a = mul_two(a, a, p);
}
return ans;
}
ll qpow(ll a, ll n, ll p)
{
ll ans = 1; a %= p;
while (n)
{
if (n & 1) ans = ans * a%p;
n >>= 1; a = a * a%p;
}
return ans % p;
}
//勒让德符号
ll Legendre(ll a, ll p) { return qpow(a, (p - 1) >> 1, p); }
//求x^2=b mod p 的解
int solve(ll b, ll p) {
if (b == 0) return 0;
if (b == 1) return 1;
if (Legendre(b, p) + 1 == p) return -1;
ll a;
while (1)
{
a = gen() % p;
ll t = a * a - b;
w = (t%p + p) % p;
if (Legendre(w, p) + 1 == p) break;
}
T tmp = { a,1 };
T ans = qpow_two(tmp, (p + 1) >> 1, p);
return ans.x;
}
#define endl '\n'
int main()
{
#ifndef endl
freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
cout << "************************************Local Test*********************************" << endl;
#endif // !endl
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int ca;cin>>ca;
while(ca--)
{
ll b, c; cin >> b >> c;
ll delta = MODED(b*b - 4*c);
ll gdel = solve(delta, mod);
// cout<
if (gdel == -1)
cout << "-1 -1" << endl;
else
{
ll inv2 = (mod + 1) / 2;
ll x = (b + gdel)*inv2%mod;
ll y = MODED(b - gdel)*inv2%mod;
x = MODED(x); y = MODED(y); if (x > y)swap(x, y);
cout << x << ' ' << y << endl;
}
}
return 0;
}
//What to Debug
/*
-1.最好把全部warning都X掉,否则:https://vjudge.net/solution/19887176
0.看看自己是否有可能需要快读,禁endl
1.数组越界,爆int,浮点精度(查看精度是否达到题目要求,看有没有浮点数比较:eps),取模操作,初始化数组,边缘数据,输出格式(cas),强制在线是否更新了las
2.通读代码,代码无逻辑错误
3.读题,找到题意理解失误或算法错误
4.放弃
*/