POJ3696 尤拉定理
阿新 • • 發佈:2020-08-16
看了兩天,poj還卡溢位。
題意
給你一個數L(2e9),找到最小的連續8組成的數且是L的倍數。沒有則輸出0。
思路
首先8個連續的數可以表示為(10x-1)*8/9。
(10x-1)*8/9 = L*k(k為任意整數)
(10x-1)*8 = L*k*9
令d = gcd(8,L)。
則兩邊同時除d
(10x-1)*(8/d) = k*(L*9)/d
由a*b=c*d且a,c互質,能推出b|c可得
10x-1|9*L/d
ze可以
然後答案即為9L/d 的尤拉函式的約數。如果10和9L/d不互質,則無解。
注意這題快速冪會溢位。
#include <iostream> #include<cstdio> #include <cmath> using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} const int maxn = 2e5+10; ll L; ll phi(ll n) { ll ans = n; for(int i = 2;i <= sqrt(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; } ll powmod(ll a, ll b, ll mod) { ll sum = 1; while (b) { if (b & 1) { sum = (sum * a) % mod;b--; } b /= 2;a = a * a % mod; } return sum; } int main() { //freopen("input.txt", "r", stdin);int casee = 0; while(scanf("%lld",&L) != EOF){ if(L == 0) break; ll d = gcd(L,8ll); ll p = 9*L/d; if(gcd(10,p) == 1){ ll k = phi(p); bool flag = 0; for(int i = 1;i <= sqrt(k);++i){ if(k%i==0 && powmod(10,i,p)==1){ printf("Case %d: %d\n",++casee,i ); flag = 1; break; } } if(flag == 1) continue; for(int i = sqrt(k);i >= 1;--i){ if(k%i==0 && powmod(10,k/i,p)==1){ printf("Case %d: %d\n",++casee,k/i ); break; } } }else printf("Case %d: 0\n",++casee ); } }