推荐一个讲的很好的文章,我的思路也是从那学来的
http://blog.csdn.net/wukonwukon/article/details/7215467
根据推倒的公式,很快就搞出来了
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long n,k; const int mod= 1000000007; typedef long long ll; int get_eulr(int n) { int ans=n; for(int i=2;i*i<=n;i++) if(n%i==0){ ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n!=1) ans=ans/n*(n-1); return ans%mod; } ll powmod(ll a,ll n) { if(a==0) return 0; a%=mod; ll ans=1; for(;n;a=a*a%mod,n>>=1) if(n&1) ans=ans*a%mod; return ans; } ll cal(int p,int n) { ll ans=powmod(p-1,n); if(n&1) ans= ((ans-p+1)%mod+mod)%mod; else ans=((ans+p-1)%mod+mod)%mod; return ans; } int main() { ll n,k; while(scanf("%I64d %I64d",&n,&k)==2) { ll ans=0,i; for(i=1;i*i<n;i++) if(n%i==0) { ans= (ans+get_eulr(i)*cal(k-1,n/i)%mod+get_eulr(n/i)*cal(k-1,i))%mod; } // cout<<ans<<endl; if(i*i==n) ans=(ans+get_eulr(i)*cal(k-1,i)%mod)%mod; ans=ans*k%mod; ans=ans*powmod(n,mod-2)%mod; printf("%I64d\n",ans); } return 0; }
xn = (p-1) * yn-1
yn= xn-1 + (p-2) * yn-1
初始值 x1= 0 , y1 = p
然后构造矩阵,就可以算出xn了
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long n,k; const int mod= 1000000007; typedef long long ll; int get_eulr(int n) { int ans=n; for(int i=2;i*i<=n;i++) if(n%i==0){ ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n!=1) ans=ans/n*(n-1); return ans%mod; } ll powmod(ll a,ll n) { if(a==0) return 0; a%=mod; ll ans=1; for(;n;a=a*a%mod,n>>=1) if(n&1) ans=ans*a%mod; return ans; } void mul(ll a[][2],ll b[][2]) { ll t[2][2]={0}; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int r=0;r<2;r++) t[i][j]=(t[i][j]+a[i][r]*b[r][j])%mod; memcpy(a,t,sizeof(t)); } ll cal(int p,int n) { ll a[2][2]={0,p-1,1,p-2},b[2][2]={0}; b[0][0]=b[1][1]=1; ll n1=n-1; for(;n1;n1>>=1,mul(a,a)) if(n1&1) mul(b,a); return p*b[0][1]%mod; } int main() { ll n,k; while(scanf("%I64d %I64d",&n,&k)==2) { ll ans=0,i; for(i=1;i*i<n;i++) if(n%i==0) { ans= (ans+get_eulr(i)*cal(k-1,n/i)%mod+get_eulr(n/i)*cal(k-1,i))%mod; } // cout<<ans<<endl; if(i*i==n) ans=(ans+get_eulr(i)*cal(k-1,i)%mod)%mod; ans=ans*k%mod; ans=ans*powmod(n,mod-2)%mod; printf("%I64d\n",ans); } return 0; }
两种方法差别还是很大的