题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1054。
题目大意 :在(y0,y1)的范围内找出有多少个数满足gcd(x,y)的深度(递归调用的次数)等于d。
解题思路:这题刚那拿到第一反应是拉梅定理,找了好久没找到合适的计算方法,经同学提醒发现随便确定一个x,在模拟一下这个过程就能找到规律,当y大于x后gcd(x,y)的深度就会出现周期性变化,这样就可以对10的9次方的范围计数了,由于x=y时比较特殊,最后特判一下,所以这题就变成了一个模拟,看来自己写代码的能力还有待提高,wrong的7发后才过
。但还是把丑的一比的代码贴在这,仅供参考。
/* ******************************** Author : danmu Created Time : 2016年04月17日 星期日 03时24分12秒 File Name : gcdDepth.cpp Vim Command copy -> yy paste -> p P del this line -> dd Ctrl-Z -> u U copy into system -> "+y ******************************** */ #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <iomanip> #include <string> #include <vector> #include <cstdio> #include <stack> #include <queue> #include <cmath> #include <list> #include <map> #include <set> #define ULL unsigned long long #define PI 3.1415926535 #define INF 0x3f3f3f3f #define LL long long #define eps 1e-8 using namespace std; int num1[200010],num2[200010]; int gcdDepth(int x,int y){ if(y==0) return 0; return gcdDepth(y,x%y)+1; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int x,d,y0,y1; while(scanf("%d%d%d%d",&x,&d,&y0,&y1)!=EOF){ int ans=0; if(x==0){ if(d==0){ if(y0==0) ans=1; } else if(d==1){ if(y0==0) ans=y1; else ans=y1-y0+1; } } else{ int flag=0,tmp; if(d==0){ if(y0==0) ans=1; flag=1; } for(int i=0;i<x&&!flag;++i){ tmp=gcdDepth(x,i); if(tmp==d) num1[i+1]=num1[i]+1; else num1[i+1]=num1[i]; if(tmp+2==d) num2[i+1]=num2[i]+1; else num2[i+1]=num2[i]; } tmp=y0; if(!flag&&tmp<x){ if(y1<x){ ans+=num1[y1+1]-num1[tmp]; flag=1; } else{ ans+=num1[x]-num1[tmp]; tmp=x; } } if(!flag&&tmp%x){ if(y1<(tmp/x+1)*x){ ans+=num2[y1%x+1]-num2[tmp%x]; flag=1; } else{ ans+=num2[x]-num2[tmp%x]; tmp+=x-tmp%x; } } //printf("%d\n",tmp); if(!flag) ans+=(y1/x-tmp/x)*num2[x]; //printf("%d %d\n",tmp,(y1/x-tmp/x)*num2[x]); if(!flag) ans+=num2[y1%x+1]; //printf("%d\n",ans); if(y0<=x&&y1>=x){ if(d==1) ++ans; else if(d==2) --ans; } } printf("%d\n",ans); } return 0; }