【zqsz&&loi 互测 11.6】 T1

原题题目来源:poj 1845
原题传送门
原题求a^b的约数个数,本题作了修改:
这里写图片描述
这里写图片描述
这里写图片描述

题目很明显是求首项为1,公比为m的等比数列的前t项和

Solution 1:等比数列通项公式+快速幂

最关键的是取模用到逆元
求逆元?exgcd?费马小定理?不行不行,题目中没有说m和t-1互质
qwq get到了dalao的求逆元的通式:
求:(a/b)%m
公式:(a/b)%m=(a%(m*b))/b
证明?
已知:b|a
设 (a/b)%m=x
a/b=km+x(x < m)
a=kbm+bx
a%(bm)=bx
a%(bm)/b=x
则:(a/b)%m=(a%(m*b))/b
(ps: qly安利给我的博客)

注意开unsigned long long
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef unsigned long long ll;
ll t,m,k,ans;

ll ksm(ll x,ll p)
{
    ll di=x,ret=1,mo=k*(m-1);
    while(p)
    {
        if(p&1) ret=(ret%mo*di%mo)%mo;
        di=(di%mo*di%mo)%mo;
        p>>=1;
    }
    return ret%mo;
}
int main()
{
    cin>>m>>t>>k;
    if(m%k==0&&k!=1) ans=1;
    else if(k==1) ans=0;
    else ans=(ksm(m,t)-1)/(m-1);
    cout<<ans;
    return 0;
}

Solution 2:二分+递归求前n项和

问题:求q^0+q^1+q^2+……+q^(t-1)
由等比数列的前n项和公式可推导得:S(m+n)=Sm+Sn*q^m
设m=n=t/2(t为偶数),代入得:
St=S(t/2)+S(t/2)*q^(t/2)①
由此式递归下去,直到t==0时,返回1
注意:
函数sum(c)所求为q^0+q^1+q^2+…q^c
当c为偶数时,数列的项数为奇数即S(c+1),公式成立的条件为:t为偶数。所以求Sc+q^c。由①式可提取公因式得:Sc=S(c/2) * (1+q^(c/2))
奇数时直接求就可以了

其他细节看代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef unsigned long long ll;
ll ans,m,t,k;

ll ksm(ll p)
{
    ll di=m,ret=1;
    while(p)
    {
        if(p&1) ret=(ret%k*di%k)%k;
        di=(di%k*di%k)%k;
        p>>=1;
    }
    return ret%k;
}
ll sum(ll c)
{
    if(c==0) return 1;
    if(c&1) return (sum(c/2)*(1+ksm(c/2+1)))%k;
    return (sum(c/2-1)*(1+ksm(c/2))%k+ksm(c))%k;
}
int main()
{
    cin>>m>>t>>k;
    ans=sum(t-1);
    cout<<ans;
    return 0;
} 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值