GCD
彼女は問題を解決することを計画して少し白、最大公約数を学んだ:所与\(X、N、\)
クエリ\(\ sum_ {= 1} ^ N \ sum_ {B = 1} ^ ngcd(X ^ A -1、X ^ B-1)\)入力
入力の最初の行は、T(1≤T≤300)の整数であり、
各テストケースについては、単一のラインは、二つの整数をxとn(1≤x、n≤1000000)が含まれ出力
各テストケースは、出力Aラインの場合、答えは十億七を国防省
サンプル入力
5
3 1
4 2
8 7
10 5
10 8サンプル出力
2
24
2398375
111465
111134466
思路:
\(ANS = \ sum_ {i = 1} ^ N(X ^ I-1)\ sum_ {J = 1} ^ {\ lfloor \ FRAC {n}は{I} \ rfloor} \ PHI(J)\ )
証明:
セット\(> B \)
\((X ^-1、X ^ B-1)=(X ^ AX ^ B、X ^ B-1)=(X ^ B(X ^ {AB} -1)、X ^ B-1) \)
\(\(X ^ B、X ^ B-1)= 1 \ため)
\(\したがって、(X ^ B(X ^ {AB} -1)、X ^ B-1)=(X ^ {AB} -1、X ^ B-1)=(X ^ {\%B- 1}、X ^ B-1)=(0、X ^ {(B)-1})= X ^ {(A、B)} - 1 \)
最適化:
シンプル、時間の複雑あれば\(O(TN)\) 、となります(\ TLE)\
以来、\(\ lfloor \ FRAC {N } {I} \ rfloor \) のみを有していて\(2 \ SQRT {N} \) の値、我々は、幾何学的分割ブロック列の和を考えます。
\(\ mathfrak {話し\は\ \ \コードをお見せし、\安いです。} \)
#pragma GCC optimize("Ofast")
#include<cstdio>
#include<algorithm>
using namespace std;
# define Type template<typename T>
# define read read1<int>()
Type inline T read1()
{
T t=0;
bool ty=0;
char k;
do k=getchar(),(k=='-')&&(ty=1);while('0'>k||k>'9');
do t=(t<<3)+(t<<1)+(k^'0'),k=getchar();while('0'<=k&&k<='9');
return ty?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define int long long
# define mod 1000000007ll
int l,r,phi[1000001],pri[1000001],s,m;
void work1(const int r=1000000)
{
phi[1]=1;
for(int i=1;i++^r;)
phi[i]=i;
for(int i=2;i<=r;++i)
{
if(phi[i]==i)
pri[++pri[0]]=i,phi[i]=i-1;
for(int j=1;j<=pri[0]&&pri[j]*i<=r;++j)
if(i%pri[j])phi[i*pri[j]]=phi[i]*(pri[j]-1);
else{phi[i*pri[j]]=phi[i]*pri[j];break;}
}
for(int i=0;i++^r;phi[i]=(phi[i]+phi[i-1])%mod);
}
int qkpow(int n,int m)
{
if(!m)return 1;
int t=qkpow(n,m>>1);
t=t*t%mod;
if(m&1)t=t*n%mod;
return t;
}
int que(int l,int r)
{
if(s==1)return r-l+1;
return qkpow(s,l)*(qkpow(s,r-l+1)-1)%mod*qkpow(s-1,mod-2)%mod;
}
void work()
{
s=read,m=read;
int ans=0,l=0,r=1;
while(l<m)
{
ans+=(que(l+1,r)-r+l)*(phi[m/r]*2-1)%mod;
ans%=mod;
l=r;
if(l==m)break;
r=m/(m/(l+1));
}
/*for(int i=0;i++^m;)
ans=(ans+(a[i]-1)*(phi[m/i]*2-1))%mod;*/
printf("%lld\n",(ans+mod)%mod);
}
signed main()
{
work1();
for(int T=read;T--;work());
return 0;
}
/*
(x^a-1,x^b-1)=(x^a-1,x^b-x^a)=(x^a-1,(x^(b-a)-1)*x^a)
=(x^a-1,x^(b-a)-1)=(x^a-1,x^(b%a)-1)
*/