2020 杭电多校一 1005 Distinct Sub-palindromes(数论 推导)

题目

题目链接

思路

在斐波那契数列的基础上进行推导,可以推出式子。
用二次剩余定理处理左侧的根号五,右边用 欧拉降幂 + 快速幂 + 逆元 等数论知识处理一下即可。
可以提前算的最好提前算一下,这道题很卡常。

出题人推出来的式子,跟我们推的不太一样,不过很相似了。
在这里插入图片描述

比赛AC,赛后RE,奇奇怪怪。

代码

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const ll mod = 1e9 + 9;
ll fac[maxn], a[maxn], b[maxn];
void init(){
    a[0] = b[0] = fac[0] = 1;
    for(int i = 1; i < maxn; i++){
        fac[i] = fac[i - 1] * i % mod;
        a[i] = a[i - 1] * 691504013 % mod;
        b[i] = b[i - 1] * 308495997 % mod;
    }
}
ll quick_pow(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b & 1){
            ans = ans * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
ll solve(ll n, ll C, ll k){
    ll ans = 0; ll val = n % (mod - 1);
    for(int r = 0; r <= k; r++){
        ll t = a[k - r] * b[r] % mod;
        t = quick_pow(t, C % (mod - 1));
        ll x = fac[k];
        ll y = fac[k-r] * fac[r] % mod;
        ll c = x * quick_pow(y, mod - 2) % mod;//逆元
        ll tmp = t * (quick_pow(t, val) - 1) % mod * quick_pow(t - 1, mod - 2) % mod;
        if(t == 1)
            tmp = n % mod;
        tmp = tmp * c % mod;
        if(r & 1)
            ans -= tmp;
        else
            ans += tmp;
        ans %= mod;
    }
    ll m = quick_pow(383008016, mod - 2);
    ans = ans * quick_pow(m, k) % mod;
    ans = (ans % mod + mod) % mod;
    return ans;
}
ll n, c, k;
int main(){
    init();
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%lld %lld %lld", &n, &c, &k);
        printf("%lld\n", solve(n, c, k));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值