[bzoj 3031] 理科男
2024-10-15 22:02:30
题意
给定一个进制分数 求是否是循环小数,且求出循环节长度
题解
暴力
il int find(int p){
int head=last[p%mod];
while(head&&pr[head].p!=p)head=pr[head].next;
if(!head)head=++siz;
return head;
} int main(){
T=gi;
while(T--){siz=0;memset(last,0,sizeof(last));
ll p,q,k;
p=gi;q=gi;k=gi;
ll d=gcd(p,q);
p/=d;q/=d;
p%=q;
for(int i=1;;i++){
p*=k;
if(!(p%q)){
printf("%d 0\n",i);
break;
}
int t=find(p);
if(!pr[t].id)pr[t]=(data){i,p};
else{
printf("%d %d\n",pr[t].id-1,i-pr[t].id);
break;
}
p%=q;
}
}
return 0;
}
正解:
首先设一个序列,表示原数小数点后i位,那么
然后余数
且
上面暴力是计算到这样一对的时候停止
那么考虑a的性质 如果 ,那么
设
如果 那么
就是出现了更早的重复,所以最早的重复肯定是在p=1,说明这样形式的只有纯循环小数
如果满足
于是
然后就是求一个K模B的阶的问题。
阶很好求。。
如果
那么设
重复这个过程,然后直到时,做了多少次,前面非循环部分长度就是t,求一遍阶就可以了
#include<queue>
#include<map>
#include<cstdio>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int>Pii;
const int inf=0x7fffffff;
const ll infll=(1ll<<60);
#define dbg(n) cerr<<#n"="<<n<<endl;
#define Ri register int
#define gc getchar()
#define il inline
il ll read(){
bool f=true;
register ll x=0;char ch;
while(!isdigit(ch=gc))
if(ch=='-')f=false;
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=gc;
}
return f?x:-x;
}
#define X first
#define Y second
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
inline ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
map<ll,int> Calc(ll x){
map<ll,int> prime;
for(int i=2;(ll)i*i<=x;i++)
if(x%i==0){
int sum=0;
while(x%i==0)x/=i,sum++;
prime[i]=sum;
}
if(x>1)prime[x]=1;
return prime;
}
il ll Euler_phi(ll x,const map<ll,int>& prime){
ll ans=x;
for(map<ll,int>::const_iterator i=prime.begin();i!=prime.end();i++)
if(i->Y)ans=ans/i->X*(i->X-1);
return ans;
}
il ll Mul(ll a,ll b,ll mod){
ll ans=0,p=a%mod;
while(b){
if(b&1)ans=(ans+p)%mod;
p=(p+p)%mod;
b>>=1;
}
return ans;
}
il ll Mod(ll a,ll b,ll mod){
ll ans=1,p=a%mod;
while(b){
if(b&1)ans=Mul(ans,p,mod);
p=Mul(p,p,mod);
b>>=1;
}
return ans;
}
ll A,B,K;
int main(){
int T;
cin>>T;
while(T--){
A=gi;B=gi;K=gi;
ll d=gcd(A,B);
A/=d;B/=d;
map<ll,int> prime_B=Calc(B),prime_K=Calc(K);
int M=0;ll tmpB=B;
for(map<ll,int>::const_iterator i=prime_K.begin();i!=prime_K.end();i++){
int p=prime_B[i->X];prime_B[i->X]=0;
M=max(M,(p+i->Y-1)/i->Y);
while(p)
tmpB/=i->X,p--;
}
ll R=0;
if(tmpB!=1){
ll phi_B=Euler_phi(tmpB,prime_B);
R=phi_B;
prime_B=Calc(R);
for(map<ll,int>::const_iterator i=prime_B.begin();i!=prime_B.end();i++){
int p=i->Y;
while(p){
if(Mod(K,R/i->X,tmpB)==1)
p--,R/=i->X;
else break;
}
}
}
cout<<M<<" "<<R<<endl;
}
return 0;
}
最新文章
- JS截字符串处理数字,汉字,英文问题
- JNI在C 和 C++ 函数实现的不同
- Java网络连接之HttpURLConnection 与 HttpClient
- RDS MySQL 全文检索相关问题的处理
- Oracle数据库入门——初级系列教程
- php 数组二分法查找函数
- 双日历插件--jq datepicker时间范围选择
- 2.3搭建Android应用程序开发环境
- c中计时的几种方法
- 解决读写properties属性文件
- spring 加载配置文件的相关配置总结
- 减小Cookie体积
- boost.asio源码阅读(1) - 从chat_server开始
- 【stm32】时钟树解析
- 近期热门微信小程序demo源码下载汇总
- java游戏开发杂谈 - 创建一个窗体
- 【转】没那么难,谈CSS的设计模式
- MyBatis-进阶1
- BZOJ3626 LNOI2014LCA(树链剖分+主席树)
- Socket传输简单的信息以及粘包问题的解决