Codeforces 963A Alternating Sum 【数论+数学】

官方题解这个样子我觉得说得比较清楚。Z我们可以朴素的预处理出来(注意乘法膜),q的话考点在于【分数取膜】即 (a/b)%P = a* inverse of b %P

这就涉及到算b的逆元,我用的是欧几里得算法。下面这个博客写的很清楚。

http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

 然后还有两个细节,一是要写快速幂这样才能 O(k * log(n)) 复杂度预处理出Z,快速幂的时候注意a的类型得是long long,因为a*a的时候可能爆int,我就因为这一点WA了好多次。第二个细节是根据等比数列求和公式我们要特判一下q=1的情况

 1 #include<iostream>
 2 #define MAXN 200000
 3 #define ll long long
 4 #define P 1000000009
 5 using namespace std;
 6 
 7 int exgcd(int a,int b,int &x,int &y)
 8 {
 9     if(b==0)
10     {
11         x=1;
12         y=0;
13         return a;
14     }
15     int r=exgcd(b,a%b,x,y);
16     int t=x;
17     x=y;
18     y=t-a/b*y;
19     return r;
20 }
21 
22 ll power(ll a,int n){
23     if(n==0) return 1;
24     if(n==1) return a;
25     if(n==2) return (a*a)%P;
26     if(n%2) return power(power(a,n/2),2)*a%P;
27     return power(power(a,n/2),2);
28 }
29 
30 
31 int n,a,b,k,s[MAXN]; 
32 int x,y;
33 ll sum;
34 
35 int main(){
36 
37 scanf("%d%d%d%d",&n,&a,&b,&k);
38 
39 for(int i=0;i<k;i++){
40     char sym; cin>>sym;
41     if(sym=='+') s[i]=1;
42     else s[i]=-1;
43 }
44 
45 for(int i=0;i<k;i++){//Z
46     if(s[i]==1) sum=(sum+power(a,n-i)*power(b,i)%P)%P;
47     else sum=(sum-power(a,n-i)*power(b,i)%P+P)%P;
48 }
49 
50 exgcd(a,P,x,y);//找a的逆元 
51 int inva=x;
52 inva+=P; inva%=P;
53 ll q = power(b,k)*power(inva,k)%P;
54 
55 if(q==1){
56     cout<<sum*((n+1)/k)%P;
57 }
58 else{
59     x=0; y=0;
60     exgcd(q-1,P,x,y); x+=P; x%=P;
61     printf("%d",sum*x%P*( power(q,(n+1)/k) -1 )%P );
62 }
63     
64     return 0;
65 }

猜你喜欢

转载自www.cnblogs.com/ZhenghangHu/p/8973537.html