POJ 2478 题意:给定一个数n,求小于或等于n的数中两两互质组成的真分数的个数。
POJ 3090 题意:一个(0, n)*(0, n)的图,从点(0,0)到点(x,y)画线段不经过其它点,问能画多少条。
思路:
POJ3090
1×1只有一个斜率为0的 2×2斜率有0,1/2(0已经算过了,以后不再算了),其实就多了一个斜率为1/2的。 3×3的时候,有1/3,2/3两个,比以前多了2个 4×4的时候,有1/4,2/4(1/2已经有过了),3/4,所以也是2个 5×5的时候,有1/5,2/5,3/5,4/5,之前都没有,所以多了4个 6×6得到时候,有1/6,2/6(1/3已经有了),3/6(1/2已经有了),4/6(2/3已经有了),5/6,所以只剩2个。
分子和分母能够约分的,前面都已经有过了,所以每次要加的个数就是分子和分母互质的个数,也就是欧拉函数
(POJ2478同理)
POJ3090代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 1e3+5; int phi[maxn], p[maxn], pNum; bool f[maxn]; int sum[maxn]; void init() { for(int i = 2; i < maxn; i++) { if(!f[i]) { p[pNum++] = i; phi[i] = i-1; } for(int j = 0; j < pNum && p[j]*i < maxn; j++) { f[p[j]*i] = 1; if(i%p[j] == 0) { phi[p[j]*i] = phi[i]*p[j]; break; } else phi[p[j]*i] = phi[i]*(p[j]-1); } } } int main(void) { init(); phi[1] = 1; for(int i = 1; i < maxn; i++) sum[i] = sum[i-1]+phi[i]; int t, ca = 1; cin >> t; while(t--) { int x; scanf("%d", &x); printf("%d %d %d\n", ca++, x, sum[x]*2+1);//加1是对角线,*2是对称的上面的三角形 } return 0; }