【BZOJ】【2219】数论之神
2015-06-02 17:17
495 查看
中国剩余定理+原根+扩展欧几里得+BSGS
题解:http://blog.csdn.net/regina8023/article/details/44863519新技能get√:
/************************************************************** Problem: 2219 User: Tunix Language: C++ Result: Accepted Time:288 ms Memory:5076 kb ****************************************************************/ //BZOJ 2219 #include<cmath> #include<map> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define pb push_back using namespace std; typedef long long LL; inline int getint(){ int r=1,v=0; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; return r*v; } const int N=1e5+10; const LL inf=1e18; /*******************template********************/ map<LL,LL> mp; struct data{ LL p,c,pc; }a ; int num,cnt; LL f ; void Split(int x){ num=0; for(int i=2;i*i<=x;i++) if (x%i==0){ a[++num].p=i; a[num].c=0; a[num].pc=1; while(x%i==0) x/=i,a[num].c++,a[num].pc*=i; if (x==1) break; } if (x!=1) a[++num].p=x,a[num].pc=x,a[num].c=1; } LL Pow(LL a,LL b,LL p){ LL r=1; for(;b;b>>=1,a=a*a%p) if (b&1) r=r*a%p; return r; } LL Get_yuangen(LL p,LL phi){ int c=0; for(int i=2;i*i<=phi;i++) if (phi%i==0) f[++c]=i,f[++c]=phi/i; for(int g=2;;g++){ int j; for(j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break; if (j==c+1) return g; } return 0; } void exgcd(LL a,LL b,LL &d,LL &x,LL &y){ if (!b) {d=a;x=1;y=0;return;} else{exgcd(b,a%b,d,y,x); y-=x*(a/b);} } LL BSGS(LL A,LL B,LL C){ int m=ceil(sqrt(C+0.5)); mp.clear(); LL now=1; F(i,1,m){ now = now*A%C; if (!mp[now]) mp[now]=i; } mp[1]=0; A=Pow(A,m,C); now=1LL; F(i,0,m){ LL d,x,y; exgcd(now,C,d,x,y); x=(x*B%C+C)%C; if (mp.count(x)) return i*m+mp[x]; now=now*A%C; } return 0; } LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;} LL solve(LL A,LL B,LL k){ LL phi=a[k].pc-a[k].pc/a[k].p, g=Get_yuangen(a[k].pc,phi); LL ind=BSGS(g,B,a[k].pc); LL ans=gcd(phi,A); if (ind%ans) return 0; return ans*Pow(a[k].p,cnt-cnt/A,inf); } int main(){ #ifndef ONLINE_JUDGE freopen("2219.in","r",stdin); freopen("2219.out","w",stdout); #endif int T=getint(); while(T--){ LL A=getint(),B=getint(),k=getint(); LL p=2*k+1; Split(p); LL ans=1; F(i,1,num){ if (!ans) break; if (B%a[i].pc==0) ans=ans*Pow(a[i].p,a[i].c-(a[i].c-1)/A-1,inf); else{ int b=B; cnt=0; while((b%a[i].p)==0){ b/=a[i].p; a[i].pc/=a[i].p; a[i].c--,cnt++; } if (cnt % A) ans=0; else ans=ans*solve(A,b,i); } } printf("%lld\n",ans); } return 0; }
View Code
2219: 数论之神
Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 410 Solved: 48
[Submit][Status][Discuss]
Description
在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神
题: 对于给定的3个非负整数 A,B,K 求出满足 (1) X^A = B(mod 2*K + 1) (2) X 在范围[0, 2K]
内的X的个数!自然数论之神是可以瞬间秒杀此题的,那么你呢?
Input
第一行有一个正整数T,表示接下来的数据的组数( T <= 1000) 之后对于每组数据,给出了3个整数A,B,K (1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8)Output
输出一行,表示答案Sample Input
3213 46290770 80175784
3 46290770 80175784
3333 46290770 80175784
Sample Output
2727
297
HINT
新加数组一组--2015.02.27Source
数论 鸣谢 AekdyCoin[Submit][Status][Discuss]
相关文章推荐
- 2015-06-02 js中的关于的移入移出触发事件的顺序
- Android Volley完全解析(二),使用Volley加载网络图片
- Android之Http通信——1.初识Http协议
- ffplay的使用
- Appium系列文章1: Appium开发环境搭建
- C# 文本框禁止复制粘贴、只能输入数字
- C# winform 右下角弹出窗口结果
- Solr之functionQuery(函数查询)
- Android Volley完全解析(一),初识Volley的基本用法
- saltstack从CentOS5.x中移除
- jQuery插件开发
- 真正的阅读者,是不需要荐书的
- 安全测试:脚本攻击与SQL注入攻击
- 自定义Actionbar
- 你真的会二分查找吗?
- Unity5.0 RPG角色扮演历险类游戏之 森林历险记
- 长时间停留在calculating requirements and dependencies 的解决方案
- 新域名正在备案,静候佳音
- 【百度地图API】如何制作多途经点的线路导航——驾车篇
- leetcode Same Tree