现在的位置: 首页 > 综合 > 正文

hdu 5186 zhx’s submissions 5187 zhx’s contest快速幂小优化

2019年02月19日 ⁄ 综合 ⁄ 共 1630字 ⁄ 字号 评论关闭

5186:求各个数位上的和并%k,k为k进制。要交c++

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
typedef long long LL;

int n , Q;
int res[205];
char str[205];
void work() {
    int mx = 0;
    memset(res , 0 , sizeof(res));
    for (int i = 0 ; i < n ; ++ i) {
        scanf("%s" , str);
        int len = strlen(str);
        reverse(str , str + len);
        for (int j = 0 ; j < len ; ++ j)
            if (isdigit(str[j]))
                res[j] += str[j] - '0';
            else
                res[j] += str[j] - 'a' + 10;
        mx = max(len , mx);
    }
    for (int i = 0 ; i < mx ; ++ i)
        res[i] %= Q;        
    while (mx > 1 && res[mx - 1] == 0)
        -- mx;
    for (int i = mx - 1 ; i >= 0 ; -- i) {
        if (res[i] < 10)
            printf("%d" , res[i]);
        else
            printf("%c" , res[i] - 10 + 'a');
    }
    puts("");
}

int main() {
    while (~scanf("%d%d",&n,&Q))
        work();
    return 0;
}

5187:n个从1到n的数重新排成一个序列,允许序列出现一个峰(最高峰或最低峰)

可知,整个序列中只有最两边的位置一定是存在一个n或者是1的,否则若1和n这两个数都在序列中间的话,整个序列势必会出现两个峰而不满足条件。那么接下来我们开始讨论:1:1放在最左,然后考虑n所在的位置(假设都是从左往右),在第二位时所有可能是C( 0,n-2),第三位为C(1,n-2)...一直到最有,共有X = c(0,n-2)+c(1,n-2).....c(n-2,n-2) = 2^(n-1)-1种可能,然后把1放在最右同理,再将1换成n,再算一次,所以一共是有X × 2 × 2 = 2 ^ n - 4,但是中间算的过程中多减去两次(1...n)
(n...1)的情况,所以加回来,那么最终答案是ans = 2 ^ n - 2,。很明显用快速幂,但是n高达10^18,在裸快速幂计算过程中肯定会爆LL,因此将中间再次二进制拆分下,时间变成lgn*lgn,就能接受了

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;

ll n, x;

ll multi( ll a, ll b )
{
	ll res = 0;
	while( b )
	{
		if( b & 1 )
		{
			res += a;
			res %= x;
		}
		a += a, a %= x, b >>= 1;
	}
	return res;
}

ll power( ll a, ll b )
{
	ll res = 1;
	while( b )
	{
		if( b & 1 )
		{
			res = multi( res, a );
		}
		a = multi( a, a ), b >>= 1;
	}
	return res;
}

int main()
{
	while( cin >> n >> x )
	{
		if( n == 1 )
		{
			cout << 1 % x << endl;
			continue;
		}
		else
		{
			ll ans = power( 2, n ) - 2;
			while( ans < 0 )
				ans += x;
			cout << ans << endl;
		}
	}
	return 0;
}

抱歉!评论已关闭.