[CLYZ2017]day9

魔法

image

solution

思路一

\(K\)是质数直接刚逆元,剩下的考虑用欧拉定理求解.

思路二

我们可以将所有数分解质因数然后记录每个质因数的指数求解.

100分

\(C_n^m=C_n^{m-1}\times\frac{n-m+1}{m}\).
根据欧拉定理:若\((a,p)=1\),则\(a^{\phi(p)}\equiv1(mod\;p)\)
所以对于与\(K\)互质的数,可以直接求逆元.
只要特别记录\(K\)的质因数的指数即可.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define K 7
#define N 400005
#define M 1000005
using namespace std;
typedef long long ll;
ll a[N],k,mul,ans,res=1ll;
int f[K],g[K],p[N],phi[M],ph,n,m,cnt;
bool b[M];
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
inline void prime(int n){
	for(int i=2;i<=n;++i){
		if(!b[i]) p[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*p[j]<=n;++j){
			b[i*p[j]]=true;
			if(!(i%p[j])){
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			phi[i*p[j]]=phi[i]*(p[j]-1);
		}
	}
}
inline int tot(int n,int k){
	int ret=0;
	while(n>=k){
		ret+=n/k;n/=k;
	}
	return ret;
}
inline ll po(ll x,int k,ll p){
	ll ret=1ll;
	while(k){
		if(k&1) ret=ret*x%p;
		x=x*x%p;k>>=1;
	}
	return ret;
} 
inline ll c(int n,int m){
	if(!m||!(n-m)) return 1ll;
	ll ret=1;
	for(int i=1,t;i<=cnt&&p[i]<=n;++i){
		t=tot(n,p[i])-tot(m,p[i])-tot(n-m,p[i]);
		ret=ret*po(1ll*p[i],t,k)%k;
		if(!ret) return ret; 
	}
	return ret;
}
inline void Aireen(){
	n=read();k=1ll*read();
	for(int i=1;i<=n;++i)
		a[i]=1ll*read();
	prime(k);
	for(int i=1;i<=cnt;++i)
		if(!(k%p[i])) g[++m]=p[i];
	ans=a[1];ph=phi[(int)(k)]-1;
	for(int i=1,x;i<n;++i){
		x=n-i;
		for(int j=1;j<=m;++j)
			while(!(x%g[j])){
				++f[j];x/=g[j];
			}
		res=1ll*x*res%k;
		x=i;
		for(int j=1;j<=m;++j)
			while(!(x%g[j])){
				--f[j];x/=g[j];
			}
		res=res*po(1ll*x,ph,k)%k;
		mul=res;
		for(int j=1;j<=m;++j)
			mul=mul*po(1ll*g[j],f[j],k)%k;
		ans=(ans+mul*a[i+1])%k;
	}
	printf("%lld\n",ans);
}
int main(){
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

相遇

image

solution

100分

利用\(lca\)求出两人的相交路径的两端点.
利用两人到两端点的时间判断两人同向异向.
如果两人同向,如果两人时间差<相交路径上的最长边,则合法.
如果两人异向,判断两人相交处是否为顶点,若是顶点,则不合法.

原文地址:https://www.cnblogs.com/AireenYe/p/CLYZ2017day9.html