指數迴圈節問題
阿新 • • 發佈:2019-02-05
今天來學習一個新的東西---指數迴圈節。在有些題目中我們需要對指數進行降冪處理才能計算。比如計算
其中和
這裡由於很大,所以需要進行降冪。那麼實際上有如下降冪公式
有了上述公式,很多題目就可以迎刃而解了。
題意:給定,和的值,求的值。其中,。
程式碼:
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N=1000005; typedef long long LL; char str[N]; int phi(int n) { int rea = n; for(int i=2; i*i<=n; i++) { if(n % i == 0) { rea = rea - rea / i; while(n % i == 0) n /= i; } } if(n > 1) rea = rea - rea / n; return rea; } LL multi(LL a,LL b,LL m) { LL ans = 0; a %= m; while(b) { if(b & 1) { ans = (ans + a) % m; b--; } b >>= 1; a = (a + a) % m; } return ans; } LL quick_mod(LL a,LL b,LL m) { LL ans = 1; a %= m; while(b) { if(b & 1) { ans = multi(ans,a,m); b--; } b >>= 1; a = multi(a,a,m); } return ans; } void Solve(LL a,char str[],LL c) { LL len = strlen(str); LL ans = 0; LL p = phi(c); if(len <= 15) { for(int i=0; i<len; i++) ans = ans * 10 + str[i] - '0'; } else { for(int i=0; i<len; i++) { ans = ans * 10 + str[i] - '0'; ans %= p; } ans += p; } printf("%I64d\n",quick_mod(a,ans,c)); } int main() { LL a,c; while(~scanf("%I64d%s%I64d",&a,str,&c)) Solve(a,str,c); return 0; }
題意:給定一個遞迴式,其中,,求的值。
分析:本題方法比較明確,先已一直遞迴上去,直到,然後從上面再一步一步走回來,每一步都可以進行指
數降冪,這裡需要判斷。
程式碼:
#include <iostream> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; typedef long long LL; int phi(int n) { int rea = n; for(int i=2; i*i<=n; i++) { if(n % i == 0) { rea = rea - rea / i; while(n % i == 0) n /= i; } } if(n > 1) rea = rea - rea / n; return rea; } LL quick_mod(LL a,LL b,LL m) { LL ans = 1; a %= m; while(b) { if(b & 1) { ans = ans * a % m; b--; } b >>= 1; a = a * a % m; } return ans; } LL check(LL a,LL b,LL p) { LL ans = 1; for(int i=1; i<=b; i++) { ans *= a; if(ans >= p) return ans; } return ans; } LL dfs(LL n,LL m) { LL p = phi(m); if(n < 10) return n; LL x = dfs(n / 10, p); LL y = check(n % 10, x, m); if(y >= m) { LL ans = quick_mod(n % 10, x + p, m); if(ans == 0) ans += m; return ans; } else return y; } int main() { int T; cin>>T; while(T--) { LL n,m; cin>>n>>m; cout<<dfs(n,m) % m<<endl; } return 0; }
題意:給定一個數組,然後有,求如下表達式的值
分析:方法基本跟上題一樣,就不多說了。注意特殊處理的情況。
程式碼:
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; typedef long long LL; const int N = 105; LL a[N],p[N]; LL phi(LL n) { LL rea = n; for(int i=2; i*i<=n; i++) { if(n % i == 0) { rea = rea - rea / i; while(n % i == 0) n /= i; } } if(n > 1) rea = rea - rea / n; return rea; } void Init(LL m) { p[0] = m; for(int i=1; i<N; i++) p[i] = phi(p[i-1]); } LL Solve(int dept,bool &f) { LL m = p[dept]; if(m == 1) { if(a[dept] > 1) f = 1; else f = 0; return 0; } if(a[dept] >= m) { f = 1; return 0; } LL t = 1; bool flag = 0; for(int i=1;i<=a[dept];i++) { t = t * i; if(t >= p[dept]) { flag = 1; t %= m; } } LL d = Solve(dept+1,f); if(f) d += phi(m); LL ans = 1; f = 0; for(int i=0;i<d;i++) { ans = ans * t; if(ans >= m) { f = 1; ans %= m; } if(flag) f = 1; } return ans; } int main() { int T; cin>>T; while(T--) { LL n,m; cin>>n>>m; for(int i=0; i<n; i++) cin>>a[i]; if(m == 1) { puts("0"); continue; } Init(m); bool f; cout<<Solve(0,f)<<endl; } return 0; }
題意:已知,,,給定和,求的值,並且有條件
成立。
分析:本題方法很巧妙,由於。本題就要用到這個,設
那麼有
可以看出又是的一個子問題,這樣一直遞迴下去最終求得結果,因為,所以一定有解。
程式碼:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
typedef long long LL;
LL phi(LL n)
{
LL rea = n;
LL t = (LL)sqrt(1.0*n);
for(int i=2;i<=t;i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0) n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}
LL power(LL a,LL b,LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}
LL Solve(LL a,LL m)
{
if(m == 1) return 0;
LL p = phi(m);
return power(a,p,m) * power(a,Solve(a,p),m) % m;
}
int main()
{
LL a,m;
bool f = 1;
while(cin>>a>>m)
{
if(f) f = 0;
else puts("");
LL ans = 1;
for(int i=1;i<=m;i++)
ans *= i;
cout<<Solve(a,ans)%ans<<endl;
}
return 0;
}
題意:給定3個整數,其中,和,求滿足下面兩個條件的
的個數。
分析:由,所以這樣就容易多了,注意有個特判。
程式碼:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef unsigned long long ULL;
int phi(int n)
{
int rea = n;
for(int i=2; i*i<=n; i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0) n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}
ULL quick_mod(ULL a,ULL b,ULL m)
{
ULL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}
ULL f[100005];
int main()
{
int T;
scanf("%d", &T);
for(int t=1; t<=T; t++)
{
ULL b, p, m;
scanf("%I64u %I64u %I64u", &b, &p, &m);
if(b == 0 && p == 1 && m == 18446744073709551615ull)
{
printf("Case #%d: 18446744073709551616\n",t);
continue;
}
int ph = phi(p);
ULL ans = 0;
if(b == 0) ans++;
f[0] = 1;
bool flag = 0;
int i;
for(i=1; i<=m; i++)
{
f[i] = f[i-1] * i;
if(f[i] >= ph)
{
f[i] %= ph;
flag = 1;
if(f[i] == 0) break;
}
if(flag)
{
if(quick_mod(i, f[i] + ph, p) == b)
ans++;
}
else
{
if(quick_mod(i, f[i], p) == b)
ans++;
}
}
for(int k=0; i<=m && k<p; i++, k++)
if(quick_mod(i, ph, p) == b)
ans += 1 + (m - i) / p;
printf("Case #%d: %I64u\n", t, ans);
}
return 0;
}