理科男
阿新 • • 發佈:2018-10-04
長度 lld 數論 eof utc void getchar 技術 for
題目描述:
對於給定的分數 A / B,求其在 K 進制下是有限小數還是循環小數。如果是有限小數,求小數點後的位數;如果是循環小數,則求混循環部分和循環節的長度又分別是多少。
註意,循環節指的是最短循環節,且混循環部分的長度也指最短。
樣例:
input:
3
1 8 10
17 99 10
217 990 10
output:
3 0
0 2
1 2
題解:及其毒瘤的數學題(然而被大佬嘲諷不懂初中數論QAQ)
結論:循環節長度= 非循環節長度=n
其中,對於此題而言,b為k,d為B/C,C為B中所有約數中滿足其質因數屬於K中最大的那個數。n為盡量大的一個正整數使得d mod K^n==1
(mmmmmp)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<queue> #include<ctime> #define MAXN 200005 #define ll long long #define maxn 15 #define maxs 1000005 #define inf 1e9 #define eps 1e-9 using namespace std; inline char gc() { static char now[1<<16],*S,*T; if (T==S) { T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF; } return *S++; } inline ll readlong() { ll x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x*=10; x+=ch-‘0‘; ch=getchar(); } return x*f; } inline int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x*=10; x+=ch-‘0‘; ch=getchar(); } return x*f; } void putint(long long t) { int ans[40]= {0}; for(; t; t/=10)ans[++ans[0]]=t%10; for(; ans[0]; ans[0]--)putchar(‘0‘+ans[ans[0]]); putchar(‘\n‘); } ll a,b,k; ll gcd(ll a,ll b){ if(b==0){ return a; } return gcd(b,a%b); } ll phi(ll x){ ll y=x; for(int i=2;(ll)i*i<=x;i++){ if(x%i==0){ y=y/i*(i-1); do{ x/=i; }while(x%i==0); } } if(x>1){ y=y/x*(x-1); } return y; } ll mul(ll a,ll b,ll p){ ll c=0; for(;b;b>>=1,a=(a<<1)%p){ if(b&1){ c=(c+a)%p; } } return c; } ll pw(ll a,ll n,ll p){ ll v=1; for(;n;n>>=1,a=mul(a,a,p)){ if(n&1){ v=mul(v,a,p); } } return v; } ll cal(ll A,ll B){ ll x=phi(B); ll y=x; for(int i=2;(ll)i*i<=x;i++){ if(x%i==0){ while(y%i==0&&pw(A,y/i,B)==1){ y/=i; } do{ x/=i; }while(x%i==0); } } if(x>1&&pw(A,y/x,B)==1){ y/=x; } return y; } int main(){ int T=read(); while(T--){ a=readlong(); b=readlong(); k=readlong(); ll g=gcd(a,b); a/=g; b/=g; int a1=0; while(1){ ll x=gcd(b,k); if(x==1){ break; } b/=x; ++a1; } printf("%d %lld\n",a1,b==1?0ll:cal(k,b)); } return 0; }
理科男