• 牛客练习赛65


    A 最值序列

    给一个长度为n的序列a 一开始你有一个数A = 0,每次可以从序列中选一个数b,令A = A + b或者A = A * b,每个数都要使用一次,加的次数要和乘的次数相同,要求最大化A,输出A对998244353取模的值

    n≤5×105且为偶数,1≤ai≤109
    

    排序一下,前一半用加,后一半用乘。

    注意取mod

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long LL;
    const int N = 5e5+10 , mod = 998244353;
    inline int read()
    {
    	register int x = 0; register char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
    	return x;
    }
    int n;
    int a[N];
    inline int add(int a , int b) { a += b; return a >= mod ? a - mod : a; }
    inline int mul(int a , int b) { return (LL)a * b % mod; }
    int main()
    {
    	n = read();
    	for(int i = 1 ; i <= n ; ++i) a[i] = read();
    	sort(a + 1 , a + 1 + n);
    	for(int i = 1 ; i <= n ; ++i) a[i] %= mod;
    	int res = 0;
    	for(int i = 1 ; i <= n / 2 ; ++i) res = add(res , a[i]);
    	for(int i = n / 2 + 1 ; i <= n ; ++i) res = mul(res , a[i]);
    	cout << res << '
    ';
    	return 0;
    }
    

    B 多重序列

    给出n个组,第i组有m个数,分别为(a_{i,j}),一组数的权值表示为该组数所有数的乘积,找出权值最大的组,输出权值对mod取模后的值

    对于每组数据给出一个k,保证(a_{i,j})是k的非负整数次幂

    1≤n,m≤2000,1≤k≤100,1≤ai,j,mod≤1012
    

    注意一下k=1的情况基本就能过 , 然而我的常数比较大,加了一点点小优化才过。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long LL;
    #define int long long
    const int N = 2e3+10;
    inline LL read()
    {
    	register LL x = 0; register char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
    	return x;
    }
    int n , m , k;
    LL mod;
    int cnt[N] , wk[N];
    
    LL mul(LL a , LL k)
    {
    	a %= mod; LL ans = 0;
    	for( ; k ; k >>= 1 , a = (a + a) % mod)
    		if(k & 1) ans = (ans + a) % mod;
    	return ans;
    }
    
    LL ksm(LL a , LL k)
    {
    	a %= mod; LL ans = 1;
    	for( ; k ; k >>= 1 , a = a * a % mod) 
    		if(k & 1) ans = ans * a % mod;
    	return ans;
    }
    
    signed main()
    {
    	n = read(); m = read(); k = read(); mod = read();
    	if(k == 1LL) return puts("1") , 0;
    	wk[0] = 1; int tot = 1;
    	for( ; 1 ; ++tot)
    	{
    		wk[tot] = wk[tot-1] * k;
    		if(wk[tot] > 1e12) break;
    	}
    	for(int i = 1 ; i <= n ; ++i)
    	{
    		LL x;
    		for(int j = 1 ; j <= m ; ++j)
    		{
    			x = read(); 
    			int p = lower_bound(wk , wk + 1 + tot , x) - wk;
    			cnt[i] += p;
    		}
    	}
    	int mx = 0;
    	for(int i = 1 ; i <= n ; ++i) mx = max(mx , cnt[i]);
    	cout << ksm(k , mx) << '
    ';
    	return 0;
    }
    

    C 二维动点

    一个二维平面上有n个点((a_i,b_i)),在一次移动中,你可以选择一个不和当前所在位置重叠的点,然后可以移动到当前所在位置和选择的点构成的直线上的任何一个位置;每次询问一个点(x,y),求出从(0,0)到达(x,y)所需要的最少移动次数,无解输出-1

    大胆猜结论, (n > 2 , 最大是2)

    大力无脑特判,

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<set>
    using namespace std;
    typedef long long LL;
    const int N = 1e5+10;
    inline int read()
    {
        register int x = 0; register char c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
        return x;
    }
    set< pair<int,int> > s;
    int a[N] , b[N];
     
    int Gcd(int a , int b) { return !b ? a : Gcd(b , a % b); }
     
    int main()
    {
        int n = read() , Q = read() , x , y , gcd;
        for(int i = 1 ; i <= n ; ++i)
        {
            a[i] = read(); b[i] = read(); gcd = Gcd(a[i] , b[i]);
            if(a[i] == 0 && b[i] == 0) {i --; n --; continue; }
            s.insert(make_pair(a[i] / gcd , b[i] / gcd));
        }
        while(Q--)
        {
            x = read(); y = read(); gcd = Gcd(x , y);
            if(x == 0 && y == 0) puts("0");
            else
            if(s.count(make_pair(x / gcd , y / gcd))) puts("1");
            else
            if(n < 2 || (int)s.size() == 1) puts("-1");
            else
            if(n > 2) puts("2");
            else
            if(a[1] + a[2] == x && b[1] + b[2] == y) puts("3");
            else puts("2");
        }
        return 0;
    }
    
  • 相关阅读:
    JavaBean 与 EJB 的区别
    MFC选项卡的实现
    MFC的图片按钮
    windows 下使用 MinGW + msys 编译 ffmpeg
    在windows使用vs2008编译live555
    C89 和 C99 标准比较
    11.求二元查找树的镜像[MirrorOfBST]
    10.排序数组中和为给定值的两个数字[Find2NumbersWithGivenSum]
    9.链表中倒数第k个结点[FindReverseKthLinkedListNode]
    8.另类方法求1+2+...+n[AnotherMethodOfCalculateSumN]
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/13110740.html
Copyright © 2020-2023  润新知