开始想了好久没看清楚题目,网格的布局到底是怎么回事?如果没弄清楚就导致题目无从下手。
这里是树来形成网格,所以每个点都是树,如1 1,就是表示一行一棵树,一列一棵树,就是总共一棵树;如2 3,就是表示一行2棵树,一列三棵树,总共6棵树;当然行列可调换,只是编程不同。
经过思考,你会发现其实这就是求两个数段内互质对的个数。
举个例子
n=5,m=10
答案
n=1时有10个与1互质
n=2时有5个与2互质
n=3时有7个与3互质
n=4时有5个与4互质
n=5时有8个与5互质
所以一共有35个
n=5,m=10的时候
ans=10/1+(10-10/2)+(10-10/3)+(10-10/2)+(10-10/5)
1 #include<stdio.h> 2 #include<string.h> 3 4 __int64 count[100001]; //用来记录1到100000中数的不同质因数的个数 5 __int64 num[100001][20]; //用来记录1到100000中数的不同质因数 6 __int64 prim[100001]; //用1或0来标记合数或质数 7 8 void init( ) //函数是对100000中的每个数进行质因数分解 9 { 10 int i; 11 int j; 12 int m; 13 memset(prim,0,sizeof(prim)); 14 memset(count,0,sizeof(count)); 15 for( i = 2; i <= 100000; i++) 16 { 17 if( prim[i] == 0 ) 18 { 19 num[i][0] = i; 20 count[i]++; 21 for( j = 2; j*i <= 100000; j++ ) 22 { 23 m = i*j; 24 prim[m] = 1; 25 num[m][count[m]] = i; 26 count[m]++; 27 } 28 } 29 } 30 } 31 32 __int64 not_prim( int i, int n, int k) //用容斥原理来计算机1到n中与i不互斥的个数 33 { 34 int j; 35 __int64 ans = 0; 36 for( j = k; j < count[i]; j++ ) 37 { 38 ans += n/num[i][j] - not_prim(i,n/num[i][j],j+1); 39 } 40 return ans; 41 } 42 43 int main( ) 44 { 45 int T; 46 int m; 47 int n; 48 int i; 49 int temp; 50 __int64 ans; 51 init( ); 52 while( scanf("%d", &T) == 1 ) 53 { 54 while( T-- ) 55 { 56 scanf("%d %d",&m,&n); 57 if ( n<m ) 58 { 59 temp = n; 60 n = m; 61 m = temp; 62 } 63 ans = n; 64 for( i = 2; i <= m; i++ ) 65 { 66 ans += n - not_prim(i,n,0); 67 } 68 printf("%I64d\n",ans); 69 } 70 } 71 return 0; 72 }