【zqsz&&loi 互测 11.6】 T1

原题题目来源:poj 1845
原题传送门
原题求a^b的约数个数,本题作了修改:
【zqsz&&loi 互测 11.6】 T1_第1张图片
【zqsz&&loi 互测 11.6】 T1_第2张图片
【zqsz&&loi 互测 11.6】 T1_第3张图片

题目很明显是求首项为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
#include
#include
#include
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<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
#include
#include
#include
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<return 0;
} 

你可能感兴趣的:(===数论/数学===,===基础算法===,二分,快速幂,乘法逆元)