[xsy2282]cake

Posted jefflyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[xsy2282]cake相关的知识,希望对你有一定的参考价值。

题意:一个$n imes n$的有标号点阵,现在用一条直线把它们分成两部分,问有多少种不同的分法

结论:方案数就是以点阵上的点为端点且不经过第三个点的线段数

对一个满足要求的线段,将其绕中点顺时针转一个小角度,所在直线是一种切割方案

对于一种分割方案,把直线逆时针旋转直到卡住,卡到的两个点(在原直线的两边且最近的点对)可以连出一条线段

水平竖直的答案为$2n(n-1)$,斜向的答案是$2sumlimits_{i=1}^nsumlimits_{j=1}^n(n-i)(n-j)[(i,j)=1]$

后面的sigma可以写成$(n-1)^2+2sumlimits_{i=1}^nsumlimits_{j=1}^{i-1}(n-i)(n-j)[(i,j)=1]$

一个结论是$sumlimits_{i=1}^{n-1}i[(n,i)=1]=frac{nvarphi(n)}2(ngeq2)$,这是因为在$ngeq3$时如果$(n,i)=1$那么$(n,n-i)=1$,刚好配成$frac{varphi(n)}2$对,而在$n=2$时又刚好满足

所以它又可以化成$sumlimits_{i=2}^n(n-i)left(nvarphi(i)-frac{ivarphi(i)}2 ight)$,展开后本质是求$sumlimits_{i=1}^ni^kvarphi(i)$

因为$sumlimits_{d|n}d^kvarphi(d)left(frac nd ight)^k=n^{k+1}$,所以直接杜教筛即可

#include<stdio.h>
#include<map>
using namespace std;
typedef long long ll;
const int T=1000000;
int p;
int mul(int a,int b){return a*(ll)b%p;}
int pr[T+10],phi[T+10],phk[T+10][3];
bool np[T+10];
void sieve(){
	int i,j,M=0;
	phi[1]=1;
	for(i=2;i<=T;i++){
		if(!np[i]){
			pr[++M]=i;
			phi[i]=i-1;
		}
		for(j=1;j<=M&&i*pr[j]<=T;j++){
			np[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	}
	for(i=1;i<=T;i++){
		phk[i][0]=(phk[i-1][0]+phi[i])%p;
		phk[i][1]=(phk[i-1][1]+mul(i,phi[i]))%p;
		phk[i][2]=(phk[i-1][2]+mul(mul(i,i),phi[i]))%p;
	}
}
map<int,int>g;
int pre(int k,int n){
	if(k==0)return n;
	if(k==1)return(ll)n*(n+1)/2%p;
	if(k==2)return(__int128)n*(n+1)*(2*n+1)/6%p;
	return((ll)n*(n+1)/2%p)*((ll)n*(n+1)/2%p)%p;
}
int S(int k,int n){
	if(n<=T)return phk[n][k];
	if(g.count(n))return g[n];
	int s=pre(k+1,n),i,nex;
	for(i=2;i<=n;i=nex+1){
		nex=n/(n/i);
		(s-=mul(pre(k,nex)-pre(k,i-1),S(k,n/i)))%=p;
	}
	return g[n]=s;
}
int getT(int n){
	int s=mul(mul(n,n),S(0,n)-1),t;
	g.clear();
	t=mul(S(1,n)-1,3);
	if(~t&1)
		t>>=1;
	else
		t=mul(t,(p+1)/2);
	(s-=mul(n,t))%=p;
	g.clear();
	t=S(2,n)-1;
	if(~t&1)
		t/=2;
	else
		t=mul(t,(p+1)/2);
	(s+=t)%=p;
	return s;
}
int main(){
	int n;
	scanf("%d%d",&n,&p);
	sieve();
	printf("%lld",((mul(2*n,n-1)+2ll*(mul(n-1,n-1)+2ll*getT(n)))%p+p)%p);
}

以上是关于[xsy2282]cake的主要内容,如果未能解决你的问题,请参考以下文章

xmlns,xmlns:xsi,xsi:schemaLocation和targetNamespace?

HDU 5355 Cake (WA后AC代码,具体解析,构造题)

如何将多个标志作为 Cake 参数传递?

HDU 5355 Cake

UVA 1629 Cake slicing

如何从 Cake 构建任务将标签推送到 Bamboo 中的 Bitbucket Git 存储库?