2021年中国大学生程序设计竞赛女生专场 E. 被遗忘的计划(生成函数,多项式卷积)

2021/11/3 17:12:05

本文主要是介绍2021年中国大学生程序设计竞赛女生专场 E. 被遗忘的计划(生成函数,多项式卷积),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目地址
思路:假定我们已经得到了k的值,那么最终的 \(f_i\) 中必然有一个值等于 \(k*max(v)\) 而且必然是 \(f_i\) 的最大值,那就好做了,找到 \(v_i\) 和 \(f_i\) 的最大值,除一下k就出来了,现在要验证这个k是否合法,也就是我要根据这个k,算出买k个物品,对于每种模数价格的价值最大值是否和 \(f_i\) 完全一样。这个我们可以考虑生成函数,其中指数表示价格,系数表示价值,那么买一个物品的生成函数如下。
\(v_n+v_1x^1+v_2x^2+...+v_{n-1}x^{n-1}\)
那么买k个物品就是该生成函数的k次方,注意,由于这题对价格要对n取模,同时价值是相加而不是相乘,所以不是传统的卷积,而是 \(f_{k}=max((f_i+f_j)[(i+j)\%n==k])\) 所以快速幂的时候手写mul函数要注意是加法。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <time.h>
#include <map>
#include <algorithm>
#include <fstream>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 400000 + 100;
const int INF = 0x7fffffff;
const ll mod = 998244353;
const ll mod1 = 998244353;
const ll base = 137;
const double Pi = acos(-1.0);
const int G = 3;
int v[maxn];
ll f[maxn];
vector<ll>a;
int n;
vector<ll> mul(vector<ll>a,vector<ll>b)
{
	vector<ll>res(n,-4e18);
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			res[(i+j)%n]=max(res[(i+j)%n],a[i]+b[j]);
		}
	}
	return res;
}
vector<ll>add(vector<ll>a,vector<ll>b)
{
	for(int i=0;i<n;i++)
	{
		a[i]+=b[i];
	}
	return a;
}
vector<ll> q_pow(vector<ll>a,ll b)
{
	vector<ll>res(n,0);
	int f=0;
	//res[0]=1;
	while(b)
	{
		if(b&1)
		{
			if(!f)
			{
				for(int j=0;j<n;j++) res[j]=a[j];
				f=1;
			}
			else
			{
				res=mul(res,a);
			}
		/*	for(int j=0;j<n;j++)
			{
				cout<<a[j]<<' ';
			}
			puts("");*/
		}
		b>>=1;
		a=mul(a,a);
	}
	return res;
}
int main()
{
	
	scanf("%d",&n);
	int mx1=-1000000000;
	ll mx2=-1000000000000000000;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&v[i]);
		mx1=max(mx1,v[i]);
	}
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&f[i]);
		mx2=max(mx2,f[i]);
	}
	ll k=mx2/mx1;
	if(mx2%mx1||k<1||k>1000000000)
	{
		puts("-1");
		return 0;
	}
//	cout<<k<<endl;
	a.push_back(v[n]);
	for(int i=1;i<=n-1;i++)
	{
		a.push_back(v[i]);
	}
	vector<ll>res=q_pow(a,k);
	int flag=1;
	for(int i=0;i<n;i++)
	{
	//	cout<<i<<' '<<res[i]<<endl;
		if(res[i]!=f[i])
		{
			flag=0;
		}
	}
	if(flag)
	{
		cout<<k<<endl;
	}
	else puts("-1");

	//system("pause");
}


这篇关于2021年中国大学生程序设计竞赛女生专场 E. 被遗忘的计划(生成函数,多项式卷积)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程