首页 > 代码库 > calc(NOIP模拟赛Round 3)
calc(NOIP模拟赛Round 3)
原题:
D e s c r i p t i o n
给三个正整数n,m和p,求(n^1+...n^m) mod p。 Input
一行,三个整数n,m和p。 Output
输出答案。 S a m p l e I n p u t
2 2 5
S a m p l e O u t p u t
1
数 据 范 围
n,p<=10^8 m<=10^17 时 限
1s
首先看到m范围就知道是快速幂了对吧。
然后我们想想看。假如是平常的快速幂的话时间复杂度为O(M)
TLE了对吧,然后我们想想有没有LOG级别的算法,就是加法也做到LOG。
考场上寻找DP式去了。。
a^1+a^2+a^3+a^4=(1+a^2)(a^1+a^2);
所以。。以此类推
f[n]=(1+f[n>>1])%p*f[n>>1]%p;
但是n为奇数的时候显然无法得到这个式子
所以奇数时:
f[n]=f[n-1]+a^n(快速幂)
然后算法复杂度O(logm)
快多啦!
然后就是代码。。
注意!在这道题中所有的数据都要定义为 long long ,否则会挂掉!
就是因为考场上太弱了,写了个int都没发现。我的70分/(ㄒoㄒ)/~~。
下面贴代码
#include<iostream> #include<cstdio> using namespace std; unsigned long long num[500]; unsigned long long n,m,p; unsigned long long ans; unsigned long long work(unsigned long long x) { unsigned long long tmp=x; unsigned long long qaq=1; int tt=1; while(tmp) { if(tmp&1)qaq=(qaq*num[tt])%p; tt++; tmp>>=1; } return qaq; } unsigned long long dfs(unsigned long long x) { if(x==1)return n%p; if(x==0)return 1; if(x%2==0)return (dfs(x/2)%p*(1+work(x/2))%p)%p; else return (dfs(x-1)%p+work(x)%p)%p; } int main(){ freopen("calc.in","r",stdin); freopen("calc.out","w",stdout); scanf("%lld%lld%lld",&n,&m,&p); unsigned long long sum=1,tot=1; num[1]=n; while(sum<m){ num[++tot]=(num[tot-1]*num[tot-1])%p; sum<<=1; } ans=dfs(m); printf("%lld\n",ans); fclose(stdin); fclose(stdout); }
calc(NOIP模拟赛Round 3)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。