YY一道题

博客围绕吃货WJH美食选择问题展开,给出题目描述,包括食物种数、美味度等条件,还说明了输入输出描述、样例及数据规模。此外提到伪暴力和标程,需计算WJH最多能吃美食种数并经公式计算后对9999991取模。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

众所周知,WJH是一个吃货,因此一顿饭他有 nnn 种食物。每一种食物都有它的美味度。可是贪心的WJH有一个尿性,他吃过一种美食就不会再吃美味度比它低的美食了而且他更喜欢吃连续的美食,不是连续的他不会吃。他又是一头健忘的pig,因此无法记得全部他吃的美食,有一些只记得范围了。
所以他要你帮忙算出他最多能吃美食的种数 valuevaluevalue
对于结果,wj当然不会满意那么容易计算,因此WJH要给wj的结果是:
∏k=value−valuevalue∏i=1k∏j=1klcm(i,j)2ij\prod_{k=value-\sqrt{value}}^{value}\prod_{i=1}^{k}\prod_{j=1}^{k}\frac{\text{lcm}(i,j)^2}{ij}k=valuevaluevaluei=1kj=1kijlcm(i,j)2
最后的结果对 999999199999919999991 (一个质数)取模。

输入描述

第一行,三个整数,n,m1,m2n,m_1,m_2n,m1,m2,分别表示食物种数,记得的美味度的具体值的个数和记得的美味度的区间的个数。
接下来 m1m_1m1 行,每行两个整数,表示记得的美味度的位置和具体值。
接下来 m2m_2m2 行,每行三个整数,表示记得的美味度的位置和范围。

输出描述

一行,一个整数,表示结果。

输入样例

    4 1 3\ \ \ \ \text{4 1 3}    4 1 3
    4 3\ \ \ \ \text{4 3}    4 3
    1 6 10\ \ \ \ \text{1 6 10}    1 6 10
    2 1 5\ \ \ \ \text{2 1 5}    2 1 5
    3 4 8\ \ \ \ \text{3 4 8}    3 4 8

输出样例

    4\ \ \ \ 4    4

样例解释

选取编号为 2,32,32,3 的食物,可以构成 value=2value=2value=2 的最优情况。
带入公式算得结果为 444

数据规模与约定

对于 10%10\%10% 的数据,有 2≤n≤1032≤n≤10^32n103n=m1n=m_1n=m1
另有 10%10\%10% 的数据,有 2≤n≤1032≤n≤10^32n103
另有 10%10\%10% 的数据,有 n=m1n=m_1n=m1
对于 50%50\%50% 的数据,有 2≤n≤5×1052≤n≤5\times10^52n5×105
对于 100%100\%100% 的数据,有 2≤n≤2×1062≤n≤2\times10^62n2×106m1+m2=nm_1+m_2=nm1+m2=n

伪暴力

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 9999991
using namespace std;
	int n,m1,m2,value=0;
	LL ans=1;
	struct node{int id,x,y;} a[100010];
	int que[1000010];
bool cmp(node x,node y)
{
	return x.id<y.id;
}
int gcd(int x,int y)
{
	return !y?x:gcd(y,x%y);
}
LL lcm(int x,int y)
{
	return (LL)x*y/gcd(x,y);
}
int main()
{
	scanf("%d %d %d",&n,&m1,&m2);
	for(int i=1;i<=m1;i++)
	{
		scanf("%d %d",&a[i].id,&a[i].x);
		a[i].y=a[i].x;
	}
	for(int i=m1+1;i<=n;i++)
		scanf("%d %d %d",&a[i].id,&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp);
	int head=1,tail=1;
	que[1]=1;
	for(int i=2;i<=n;i++)
	{
		while(head<=tail&&a[que[head]].x>a[i].y) head++;
		value=max(value,i-que[head-1]);
		while(head<=tail&&a[que[tail]].x<=a[i].x) tail--;
		que[++tail]=i;
	}
	printf("%d\n",value)
	for(int k=1;k<=value;k++)
		for(int i=1;i<=k;i++)
			for(int j=1;j<=k;j++)
				ans=(ans*lcm(i,j)*lcm(i,j)/((LL)i*j))%mod;
	printf("%lld",ans);
}

标程

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define R register
#define LL long long
#define mod 9999991
#define MAXN 200010
using namespace std;
	int n,m1,m2,value=0;
	LL ans=1;
	struct node{int id,x,y;} a[MAXN];
	int que[MAXN],prime[MAXN],inv[mod];
	LL phi[MAXN],sum_phi[MAXN],fac[MAXN];
bool cmp(node x,node y)
{
	return x.id<y.id;
}
void init(int ma)
{
	int t=0;
	phi[1]=1;
	for(R int i=2;i<=ma;i++)
	{
		if(!phi[i]) prime[++t]=i,phi[i]=i-1;
		for(int j=1;j<=t&&i*prime[j]<=ma;j++)
		{
			if(!(i%prime[j]))
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
	fac[0]=1;
	for(R int i=1;i<=ma;i++)
	{
		sum_phi[i]=sum_phi[i-1]+phi[i];
		fac[i]=fac[i-1]*i%mod;
	}
	inv[0]=inv[1]=1;
	for(R int i=2;i<mod;i++)
		inv[i]=(int)((LL)(mod-mod/i)*inv[mod%i]%mod);
}
LL dg(LL x,LL k)
{
	if(!k) return 1;
	LL op=dg(x,k>>1);
	if(k&1) return op*op%mod*x%mod; else return op*op%mod;
}
LL work(int n)
{
	LL sum=1;
	for(R int l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		sum=sum*dg(fac[r]*inv[fac[l-1]]%mod,sum_phi[n/l]*2-1)%mod;
	}
	return dg(fac[n],n*2)*inv[sum*sum%mod]%mod;
}
int main()
{
	scanf("%d %d %d",&n,&m1,&m2);
	for(R int i=1;i<=m1;i++)
	{
		scanf("%d %d",&a[i].id,&a[i].x);
		a[i].y=a[i].x;
	}
	for(R int i=m1+1;i<=n;i++)
		scanf("%d %d %d",&a[i].id,&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp);
	int head=1,tail=1;
	que[1]=1;
	for(R int i=2;i<=n;i++)
	{
		while(head<=tail&&a[que[head]].x>a[i].y) head++;
		value=max(value,i-que[head-1]);
		while(head<=tail&&a[que[tail]].x<=a[i].x) tail--;
		que[++tail]=i;
	}
	init(MAXN);
	for(R int i=value-sqrt(value);i<=value;i++)
		ans=(ans*work(i))%mod;
	printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值