1. 程式人生 > >Codeforces 963A Alternating Sum 【數論+數學】

Codeforces 963A Alternating Sum 【數論+數學】

bsp 題解 printf cin ace 一點 比較 圖片 name

技術分享圖片

官方題解這個樣子我覺得說得比較清楚。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 }

Codeforces 963A Alternating Sum 【數論+數學】