Topcoder SRM 358:SameDigits

定义一个函数f(n)表示中最长的一个序列,这个序列有相同的数字组成。
比如f(344488)=3,f(123)=1
现在给定两个整数n,k要求出有多少个数x,满足x的位数不大于n且f(x)=k.由于结果会很大,只用求出结果mod 44444444的值就可以了。

先考虑有多少个n位数x,满足f(x)=k.
我们从左往右来天数,需要记录的状态信息是:
1)有多少位数字要填
2)  此前填的数字末尾有多少位是相同的
3)  此前填的数字是否已经达到了要求(即最长的连续相同的数字序列长度为k)
我们记此状态为f(n,last_same,did_reach),这样很容易建立递推关系。
那么,刚好为n位数的结果就是9*f(n-1,1,false)

public class SameDigits {
    
final static long MOD = 44444444;
    
long[][][] memo;
    
int K;

    
long f( int n, int last_same, int did_reach ){
        
if( memo[n][last_same][did_reach] != -1 ) return memo[n][last_same][did_reach];

        
if( n == 0 ){
            
if( did_reach == 1 || last_same == K ) {
                
return memo[n][last_same][did_reach] = 1;
            } 
else {
                
return memo[n][last_same][did_reach] = 0;
            }
        }
        
if( k == K ) return memo[n][last_same][did_reach] = ( 9*f( n-111 ) )%MOD;

        
return memo[n][last_same][did_reach] = 
            ( f( n
-1, k+1, did_reach ) + 9*f( n-11, did_reach ) )%MOD;
    }

    
public int howMany( int n, int k ) {
        K 
= k;
        memo 
= new long[ n+1 ][ k+1 ][2];

        
forint i = 0; i < memo.length; ++i ) 
            
forint j = 0; j < memo[i].length; ++j ) Arrays.fill( memo[i][j], -1 );

        
long sol = 0;
        
forint i = k; i <= n; ++i ){
            sol 
= (sol + 9*f( i-110 )) % MOD;
        }
        
        
return (int)sol;
    }
}


posted on 2007-07-20 19:55  woodfish  阅读(283)  评论(0编辑  收藏  举报

导航