2026.8.17

A

P2155 [SDOI2008] 沙拉公主的困惑 https://www.luogu.com.cn/problem/P2155

首先因为 \(\gcd(x,y)=\gcd(x+ky,y)\),发现有周期性,\(\forall k \in [1,\frac{n!}{m!}],[(k-1)m!+1,km!]\) 的质数都是相等的。所以答案为 \(\dfrac{n!}{m!}\varphi(m!)\)

需要用到的公式(其中 \(p\) 均为质数)

\[\varphi\left(x\right)=x\cdot\prod_{p\left|x\right.}^{}\left(1-\frac{1}{p}\right)=x\cdot\prod_{p\left|x\right.}^{}\left(\frac{p-1}{p}\right) \]

然后发现 \(p|m!\)\(p \le m\) 是等价的,因为:

  • \(p \le m\),显然这个连乘因子一定会包含 \(p\)
  • \(p > m\)\(m!\) 肯定不会包含 \(>m\) 的质因子。

\[\begin{aligned} \text{ans} &= \frac{n!}{m!}\cdot \varphi(m!) \\ &= \frac{n!}{m!}\cdot m!\prod_{\substack{p\,\mid\,m!}} \frac{p-1}{p} \\ &= n!\cdot \frac{\displaystyle\prod_{\substack{p\in\mathbb{P}\\ p\le m}} (p-1)}{\displaystyle\prod_{\substack{p\in\mathbb{P}\\ p\le m}} p} \end{aligned} \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
constexpr int N=1e7+3;
ll n,m,mod,fac[N];  //fac[i]:<=p[i]的所有质数的乘积
vector<int> p; bitset<N> vis;
ll fac1[N],fac2[N];  //n!,分子
void sieve(int V)
{
	vis[1]=1;
	for(int i=2;i<=V;i++)
	{
		if(!vis[i]) p.push_back(i);
		for(int j:p)
		{
			if(i*j>V) break;
			vis[i*j]=1;
			if(i%j==0) break;
		}
	}
}
ll specialjudge()
{
	cin>>n>>m;
	if(m>=3) return 0;
	else   //m=1或2,n>=m
	{
		if(m==2)
		{
			if(n==2||m==3) return 1;
			else return 0;
		}
		else
		{
			if(n==1) return 1;
			else return 0;
		}
	}
}
ll ksm(ll a,ll b)
{
	ll s=1;
	while(b)
	{
		if(b&1) s=s*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return s;
}
ll solve()
{
	cin>>n>>m;
	if(m==1) return fac1[n];
	if(n>=2*mod) return 0;   //n!有2个mod,分母有0/1个mod,约不到
	if(n>=mod&&m<mod) return 0; //n!有1个mod,分母有0个mod
	int id=upper_bound(p.begin(),p.end(),m)-p.begin()-1;
	// cerr<<p[id]<<' '<<fac1[n]<<' '<<fac2[id]<<' '<<fac[id]<<'\n';
	return fac1[n]*fac2[id]%mod*ksm(fac[id],mod-2)%mod;
}
int main()
{
//	freopen("neuvillette.in","r",stdin);
//	freopen("neuvillette.out","w",stdout);
	cin.tie(0)->sync_with_stdio(0);
	int T;
	cin>>T>>mod;
	if(mod==2) while(T--) cout<<specialjudge()<<'\n';
	fac1[0]=1;
	for(int i=1;i<=1e7+3;i++)
	{
		if(i==mod) fac1[i]=fac1[i-1];
		else fac1[i]=(fac1[i-1]*i)%mod;
	}
	// for(int i=1;i<=10;i++) cerr<<fac1[i]<<" \n"[i==10];
	sieve(1e7+3);
	fac[0]=2; fac2[0]=1;
	for(int i=1;i<(int)p.size();i++)
	{
		if(p[i]==mod) fac[i]=fac[i-1];
		else fac[i]=(fac[i-1]*p[i])%mod;
		fac2[i]=(fac2[i-1]*(p[i]-1))%mod;
	}
	while(T--) cout<<solve()<<'\n';
	cout.flush();
	return 0;
}
/*
$$ n!\cdot\frac{\prod_{p\le m}^{}\left(p-1\right)}{\prod_{p\le m}^{}\left(p\right)} $$
注意n!和分母能不能约分一个mod
然后初始化阶乘遇到mod直接扔掉就好了
分母不用取模的,因为mod是质数,然后分母都是p-1?需要特判mod=2?
*/

D

P1800 [ICPC 2005 Tehran R] Software https://www.luogu.com.cn/problem/P1800

首先发现直接算出 \(t\) 非常困难。所以可以先固定 \(t\) 分析一下。

\(dp(i,x)\) 表示前 \(i\) 个人做 \(x\) 个零件 1,剩下时间全部去做零件2,能做出零件 2 的最大个数。

考虑前 \(i-1\) 个人做了 \(j-k\) 个模块 1,第 \(i\) 个人做了 \(k\) 个模块 1。

\[dp\left(i,x\right)=\max_{k=0}^{x}\left\lbrace dp\left(i-1,x-k\right)+\left\lfloor\frac{t-k\cdot d1_{i}}{d2_{i}}\right\rfloor\right\rbrace \]

显然时间越短越难完成,所以答案具有单调性,直接二分 \(t\) 即可。

posted @ 2026-08-17 21:08  wwwidk1234  阅读(4)  评论(0)    收藏  举报