http://poj.org/problem?id=2773 (Topic link)
Test instructions: Give two number m,k, ask to find the number of K from 1 and M coprime.
Solution
The data range is very large, direct simulation is obviously not possible, we need to use some strange methods.
Consider whether the solution can be quickly obtained in some way, but there is no clue. It is difficult to reverse, can not be calculated by the number of M coprime to get the number of coprime? The answer is workable, and we can use the repulsion.
A two-part answer to the mid, the tolerance statistics out in the interval [1,mid] is the number of multiples of M's mass factor ans, and then we can use Mid-ans to get the number of the interval with M coprime, and continue to two points, until the answer is reached.
The classic application of the tolerance statistics.
Code:
poj2773#include<algorithm> #include <iostream> #include <cstdlib> #include <cstring># include<cstdio> #include <cmath> #define LL long long#define inf (1ll<<62); #define Pi ACOs (-1.0) # Define free (a) freopen (a ".", "R", stdin), Freopen (a ". Out", "w", stdout); using namespace Std;int n,cnt,p[500],a[200], VIS[2010]; LL Ans,m,k,mid; ll GCD (ll A,ll b) {return a%b==0 b:gcd (b,a%b);} void Dfs (int x,int y,int z) {if (x==n+1) {if (y>0) {if (y&1) ans+=mid/z; else ans-=mid/z; } return; } dfs (X+1,Y,Z); LL TMP=A[X]/GCD (z,a[x]); if (double) tmp*z<=mid) DFS (X+1,Y+1,Z*TMP);} int main () {for (Int. i=2;i<=2000;i++) if (!vis[i]) {for (int j=i+i;j<=2000;j+=i) vis[j]=1; P[++cnt]=i; } while (scanf ("%lld%lld", &m,&k)!=eof) {memset (a,0,sizeof (a)); n=0; for (int i=1;i<=cnt;i++) if (m%p[i]==0) {while (m%p[i]==0 && m>1) M/=p[i]; A[++n]=p[i]; } if (m>1) a[++n]=m; Sort (a+1,a+1+n); LL L=1,r=inf; while (L<r) {mid= (l+r) >>1; Ans=0;dfs (1,0,1); if (mid-ans>=k) R=mid; else l=mid+1; } printf ("%lld\n", L); } return 0;}
"poj2773" Happy 2006