ural 1907 Coffee and Buns
题意:
给定一个a和n,求在1-n之间有几个数x,满足gcd(4(a+x),a^2+x^2)>1
思路:
比赛的时候打表看出了规律,结果容斥都写错了,囧!
赛后看了佳哥和尧神的思路,我想问自己智商在哪!!T^T
gcd(4(a+x),a^2+x^2)>1 ----> gcd(a+x,(a+x)^2-2ax)>1 (4是无关紧要的,如果没有4的时候不成立,加上4也不成立) ----> gcd(a+x,2ax)>1 (gcd(a,b)=gcd(b,a%b)
假设a是偶数,那么gcd(a+x,2ax)>1 ----> gcd(a+x,ax)
设最大公约数为g,则g|ax,g|a+x
如果g|a,那么g|x,如果g|x,那么g|a,所以只要x是a任意一个因子的倍数就合法
假设a是奇数,那么有2种情况
1.x是奇数
2.x是a任意一个因子的倍数
正好和打表的规律一样,哈哈,好有趣~~
代码:
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 typedef long long LL; 6 7 const int N=1100000; 8 int pr[N],p[N/10],lp; 9 LL fac[100],ans,num; 10 void gp(){ 11 for(int i=2;i<N;i++){ 12 if(!pr[i])p[lp++]=pr[i]=i; 13 for(int j=0;j<lp && i*p[j]<N;j++){ 14 pr[i*p[j]]=p[j]; 15 if(i%p[j]==0)break; 16 } 17 } 18 } 19 void dfs(int st,int end,int cnt,int need,LL n){ 20 if(cnt==need){ 21 if(cnt&1){ 22 ans = ans+n; 23 } 24 else{ 25 ans = ans-n; 26 } 27 return; 28 } 29 for(int i=st;i<end;i++){ 30 dfs(i+1,end,cnt+1,need,n/fac[i]); 31 } 32 } 33 void getfactor(LL a){ 34 num = 0; 35 for(int i=0;i<lp;i++){ 36 if(p[i]>a) break; 37 if(a%p[i]==0){ 38 fac[num++]=p[i]; 39 while(a%p[i]==0){ 40 a/=p[i]; 41 } 42 } 43 } 44 if(a!=1) fac[num++] = a; 45 } 46 int main() 47 { 48 LL a,n; 49 gp(); 50 cin>>a>>n; 51 ans=0; getfactor(a); 52 if(a&1){ 53 ans+=(n+1)/2; 54 for(int i=1;i<=num;i++) 55 dfs(0,num,0,i,n/2); 56 cout<<ans<<endl; 57 } 58 else{ 59 for(int i=1;i<=num;i++) 60 dfs(0,num,0,i,n); 61 cout<<ans<<endl; 62 } 63 return 0; 64 }