zoukankan      html  css  js  c++  java
  • Gym100851G Generators 思维 (鸽笼原理)

    网址:https://codeforces.com/gym/100851

    题意:

    考虑如下线性同余发生器:$x=(a*x+b)mod$ $c$,给出$1e4$个线性同余发生器,在这些线性同余发生器生成的数的序列中每一个序列都任意挑一个数,使得它们的和最大并且不被$k$整除,输出和的值和各个位置,如果不存在输出$-1$。$cleq1e3$。

    题解:

    线性同余发生器的值一定在不超过$c$个数就重复循环。所以只需要取其生成的前$c$个数的第k大。如果它们的和不被$k$整除,直接输出即可,如果被$k$整除,找到某个序列的第二大,使其和第一大的差值最小,且差值不被$k$整除,换上这个第二大即可。

    (很奇怪,我不知道为什么我排序了还不能直接按顺序取第二大而是需要更新,不然会$WA$)。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e4 + 5;
    typedef long long ll;
    vector<pair<int, int> >v;
    pair<int, int>p[N], dif[N];
    bool vis[1005];
    int main()
    {
    #ifndef _Aya
    	//freopen("generators.in", "r", stdin);
    	//freopen("generators.out", "w", stdout);
    #endif
    	int n, k, a, b, c, x;
    	scanf("%d%d", &n, &k);
    	for (int i = 1; i <= n; ++i)
    	{
    		memset(vis, 0, sizeof(vis));
    		v.clear();
    		scanf("%d%d%d%d", &x, &a, &b, &c);
    		v.push_back(make_pair(x, 0));
    		vis[x] = 1;
    		for (int j = 1; j < c; ++j)
    		{
    			x = (a * x + b) % c;
    			if (!vis[x])
    				v.push_back(make_pair(x, j)), vis[x] = 1;
    			else
    				break;
    		}
    		dif[i] = make_pair(-1, -1);
    		sort(v.begin(), v.end(), greater<pair<int, int> >());
    		p[i] = v[0];
    		for (int j = 1; j < v.size(); ++j)
    			if ((v[0].first - v[j].first) % k != 0 && v[j].first > dif[i].first)
    				dif[i] = v[j];
    		assert(p[i].first > dif[i].first);
    	}
    	ll sum = 0;
    	for (int i = 1; i <= n; ++i)
    		sum += p[i].first;
    	if (sum % k)
    	{
    		printf("%lld
    ", sum);
    		for (int i = 1; i <= n; ++i)
    			printf("%d%c", p[i].second, " 
    "[i == n]);
    	}
    	else
    	{
    		int minn = 1e4, minpos = 0;
    		for (int i = 1; i <= n; ++i)
    			if (dif[i].second != -1 && p[i].first - dif[i].first < minn)
    				minn = p[i].first - dif[i].first, minpos = i;
    		if (!minpos)
    			printf("-1
    ");
    		else
    		{
    			p[minpos] = dif[minpos];
    			sum -= minn;
    			printf("%lld
    ", sum);
    			for (int i = 1; i <= n; ++i)
    				printf("%d%c", p[i].second, " 
    "[i == n]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    javaweb地图定位demo
    java基础循环
    java实现时钟
    栈和队列
    线程池
    java死锁及解决方案
    克隆
    算法与数据结构基础一
    重定向与转发的区别
    省选模拟57
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/12589389.html
Copyright © 2011-2022 走看看