zoukankan      html  css  js  c++  java
  • 10.12 模拟赛

    10.12 模拟赛

    T1

    首先有一个显然可以得到的结论,每次减去最大值一定最优。

    只会最无脑的做法。。每次减去最大值,复杂度 $ O(n) $ ,虽然减了一些枝但还是显然过不去

    其实感觉60分做法就很有意思了。

    对于 $ n leq 10^{12} $

    考虑分开考虑前六位和后六位,这个时候前六位的变化只有 $ O(sqrt n) $ 次。

    考虑当前六位的最大值为某一个值时,后六位分别需要多少次才可以变成负数,以及会变成多少

    复杂度是 $ O(sqrt n) $

    对于 $ n leq 10^{18} $

    也是一个挺奇妙的搞法吧?

    类似于前面根号的做法,考虑用 $ f[i][j][k] $ ,(i) 位数,表示当前 $ i - 1 $ 位都是9,个位是 $ j $ ,且每次操作如果数位最大值小于 $ k $ 就减去 $ k $ 否则就减去数位最大值,需要多少次会减成负数,同时还要记录负数是多少。注意,每次减的都是一到九的一个数,所以最后得到的数仍然是一个前一段是9的数。

    这个式子递推的过程其实就是一个模拟的过程,就是

    9 | 9999.....999 j
    8 | 9999.....999 j'
    7 | 9999.....999 j''
    ...
    0 | 9999.....999 j'''''...
    

    这样一层一层推的,每次剩下的j都是由上一次剩下的来的。


    这题更加难在于怎么统计答案,但是题解没写。。

    我们可以先把这个数字减成 fo 的形式,这个时候就可以愉快地统计答案了

    而减法就是一个模拟的过程。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<bitset>
    using namespace std;
    #define int long long
    typedef long long ll;
    #define MAXN 1006 
    #define pb push_back
    #define pii pair<int,int>
    #define fi first 
    #define se second
    #define mp make_pair
    #define inf 0x3f3f3f3f
    #define cmx( a , b ) a = max( a , b )
    #define cmn( a , b ) a = min( a , b )
    #define upd( a , b ) ( a = ( a + b ) % P )
    //#define P 1000000007
    int n;
    int f[19][10][10] , re[19][10][10];
    void init() {
    	for( int i = 0 ; i <= 9 ; ++ i )
    		for( int j = 0 ; j <= 9 ; ++ j ) 
    			if( i < j ) 
    				f[1][i][j] = 1 , re[1][i][j] = 10 + i - j;
    			else 
    				f[1][i][j] = 2 , re[1][i][j] = 10 - j;
    	for( int i = 2 ; i <= 18 ; ++ i ) 
    		for( int j = 0 ; j <= 9 ; ++ j ) 
    			for( int k = 0 ; k <= 9 ; ++ k ) {
    				re[i][j][k] = j;
    				for( int s = 9 ; s >= 0 ; -- s ) 
    					f[i][j][k] += f[i-1][re[i][j][k]][max( s , k )],
    					re[i][j][k] = re[i-1][re[i][j][k]][max( s , k )];
    			}
    }
    int num[19];
    int make_your_dream_come_true( int x ) {
    	int fk = 0;
    	while( x ) 
    		num[++ fk] = x % 10 , x /= 10;
    	int cur = num[1] , ans = 0;
    	for( int i = 2 ; i <= fk ; ++ i ) {
    		while( num[i] != 9 ) {
    			int mx = 0;
    			for( int j = i ; j <= fk ; ++ j ) cmx( mx , num[j] );
    			if( !mx ) break;
    			ans += f[i - 1][cur][mx];
    			cur = re[i - 1][cur][mx];
    			-- num[i];
    			for( int j = i ; num[j] < 0 ; ++ j ) 
    				num[j] = 9 , -- num[j + 1];
    		}
    	}
    	for( int i = fk ; i >= 2 ; -- i ) 
    		while( num[i] ) 
    			ans += f[i-1][cur][num[i]] , cur = re[i-1][cur][num[i]] , -- num[i];
    	if( cur ) ++ ans;
    	return ans;
    }
    signed main() {
    	cin >> n;
    	init();
    	cout << make_your_dream_come_true( n ) << endl;
    	
    }
    /*
     * Things you should pay attention to
     * inf is big enough?
     * out of bounds?
     * long long ?
     */
    

    T2

    水题,就是板子的矩形数点,就不放了

    T3

    李超线段树板子,先挖坑

  • 相关阅读:
    怎样提高开发效率
    ASP.NET/C#获取文章中图片的地址
    listBox的用法
    ASP.NET中的asp:label和asp:literal
    ID,ClientID,UniqueID的区别
    asp.net中的属性
    数据库中的值为空的判断 ,并赋初值
    属性器,转换从数据库中读取的状态
    Collections.emptyList() and Collections.EMPTY_LIST
    InnoDB
  • 原文地址:https://www.cnblogs.com/yijan/p/11662116.html
Copyright © 2011-2022 走看看