题目分析:这题其实在OEIS上有这么一个数列你感信?设odd_cnt[ i ]表示i的奇约数的个数,令sum[ i ] = odd_cnt[ 1 ] + odd_cnt[ 2 ] + ... + odd_cnt[ i ]。则答案就是1 + n + sum[ n - 1] 。求一个数的奇约数可以用素数筛思想求。原数列差分两次后就是1~n的奇约数个数的数列,这个真心不容易知道。。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define CLR( a , x ) memset ( a , x , sizeof a )
typedef long long LL ;
const int MAXN = 10000005 ;
LL sum[MAXN] ;
void fun () {
CLR ( sum , 0 ) ;
for ( int i = 1 ; i < MAXN ; i += 2 ) for ( int j = i ; j < MAXN ; j += i ) sum[j] ++ ;
REP ( i , 1 , MAXN ) sum[i] += sum[i - 1] ;
REP ( i , 1 , MAXN ) sum[i] += sum[i - 1] ;
}
void solve () {
int n ;
scanf ( "%d" , &n ) ;
printf ( "%I64d\n" , 1 + n + sum[n - 1] ) ;
}
int main () {
int T , cas = 0 ;
fun () ;
scanf ( "%d" , &T ) ;
while ( T -- ) {
printf ( "Case #%d:\n" , ++ cas ) ;
solve () ;
}
return 0 ;
}