YY一道题

题目描述

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

输入描述

第一行,三个整数, n , m 1 , m 2 n,m_1,m_2 ,分别表示食物种数,记得的美味度的具体值的个数和记得的美味度的区间的个数。
接下来 m 1 m_1 行,每行两个整数,表示记得的美味度的位置和具体值。
接下来 m 2 m_2 行,每行三个整数,表示记得的美味度的位置和范围。

输出描述

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

输入样例

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

输出样例

     4 \ \ \ \ 4

样例解释

选取编号为 2 , 3 2,3 的食物,可以构成 v a l u e = 2 value=2 的最优情况。
带入公式算得结果为 4 4

数据规模与约定

对于 10 % 10\% 的数据,有 2 n 1 0 3 2≤n≤10^3 n = m 1 n=m_1
另有 10 % 10\% 的数据,有 2 n 1 0 3 2≤n≤10^3
另有 10 % 10\% 的数据,有 n = m 1 n=m_1
对于 50 % 50\% 的数据,有 2 n 5 × 1 0 5 2≤n≤5\times10^5
对于 100 % 100\% 的数据,有 2 n 2 × 1 0 6 2≤n≤2\times10^6 m 1 + m 2 = n m_1+m_2=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);
}

猜你喜欢

转载自blog.csdn.net/zsyz_ZZY/article/details/89029589