8月3日做题日记

8月3日刷题日记

P5689 [CSP-S2019 江西] 多叉堆

准确来说应该是昨天最后一道,但是某种原因没有做(((

数数题。

本质上是问一棵完全二叉树有多少种拓扑序。

乘法原理。\(f[i]=f_[i] \times f[son] \times C_{Size_i-1}^{Size_{son}}\)

除去 \(i\) 节点还剩 \(Size[i]-1\) 个节点,在里面选 \(Size[son]\) 个填入子树中,乘起来就行。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,q,ls;
int Size[N],fac[N],fa[N],Ans[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}

int Pow(int a,int b){
	int res=1;a%=Mod;
	while(b){
		if(b&1) res=(res*a)%Mod;
		b>>=1;a=(a*a)%Mod;
	}return res;
}

void Init(){
//	inv[1]=1;
	fac[0]=1;
	for(int i=1;i<=n;i++)fa[i]=i,Size[i]=Ans[i]=1;
	for(int i=1;i<=n;i++)fac[i]=(fac[i-1]*i)%Mod; 
}
int C(int n,int m){return fac[n]%Mod*Pow(fac[m],Mod-2)%Mod*Pow(fac[n-m],Mod-2)%Mod;}

signed main() {
	n=read(),q=read();Init();
	for(int i=1;i<=q;i++){
		int opt=read();
		if(opt&1){
			int x=(read()+ls)%n+1,y=(read()+ls)%n+1;
			int uf=find(x),vf=find(y);
			Ans[vf]=(Ans[uf]%Mod*Ans[vf]%Mod*C(Size[vf]-1+Size[uf],Size[uf])%Mod)%Mod;
			fa[uf]=vf;Size[vf]+=Size[uf];
		}else{
			int x=(read()+ls)%n+1;x=find(x);
			printf("%lld\n",Ans[x]);ls=Ans[x];
		}
	}
	return 0;
}

P1350 车的放置

数数题。

噶开分成两块。

上面 \(a \times b\) 和下面 \(d \times (a+c)\),不在同一行和同一列就是选 \(k\) 行和 \(k\) 列。

\(n \times n\) 的矩形中选取 \(k \times k\) 个点满足上面的条件就是 \(C_n^k \times C_n^k\),然后在选出来的点组成的矩形中共有 \(k!\) 种选法,乘法原理,第一行有 \(k\) 种选法,第二行有 \(k-1\) 种……

下面那个矩形同理。

答案就是:\(\displaystyle \sum_{i=0}^{k} i! \times C_{a}^{i} \times C_{c}^{i} \times (k-i)! \times C_{a+c-i}^{k-i} \times C_{d}^{k-i}\)

模数不是很大,用 Lucas 解决。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=1e5+3;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

void print(int x){
	if(x>9) print(x/10);
	putchar(x%10+'0');
}

int Pow(int a,int b){
	int res=1;while(b){if(b&1) res=(res*a)%Mod;
    b>>=1;a=(a*a)%Mod;}return res;
}

int a,b,c,d,k,fac[N],inv[N];

void init(){
	fac[0]=1;
	for(int i=1;i<=N-2;i++) fac[i]=(fac[i-1]*i)%Mod;
	for(int i=0;i<Mod;i++) inv[i]=Pow(i,Mod-2);
}
int C(int n,int m){	return fac[n]%Mod*inv[fac[m]]%Mod*inv[fac[n-m]]%Mod;}

int Lucas(int n,int m){
	if(!m) return 1;
	return Lucas(n/Mod,m/Mod)*C(n%Mod,m%Mod)%Mod;
}

signed main() {
	a=read(),b=read(),c=read(),d=read(),k=read();
	init();int Ans=0;
	for(int i=0;i<=k;i++){
		if(i>a||i>b||k-i>a+c-i||k-i>d) continue;
		int res=1;
		res*=fac[i];if(res) res%=Mod;
		res*=Lucas(a,i);if(res) res%=Mod;
		res*=Lucas(b,i);if(res) res%=Mod;
		res*=fac[k-i];if(res) res%=Mod;
		res*=Lucas(a+c-i,k-i);if(res) res%=Mod;
		res*=Lucas(d,k-i);if(res) res%=Mod;
		if(res==0) continue;Ans+=res;if(Ans) Ans%=Mod;
	}
	print(Ans%Mod);
	return 0;
}

P6057 [加油武汉]七步洗手法

数数题,随便搞一下就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int d[N],n,m;

signed main() {
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		d[u]++;d[v]++;
	}int ans=0;
	for(int i=1;i<=n;i++) ans+=(d[i]*(n-1-d[i]));
	cout<<n*(n-1)*(n-2)/6-ans/2;
	return 0;
}

P3223 [HNOI2012] 排队

正难则反,老师不相邻 = 全部 - 老师相邻。

然后再贺上一个傻逼高精就过了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define LL long long

const int Mod = 1e9 + 7;
const int N = 1e6 + 7, M = 2e3 + 1;

using namespace std;

inline int read() {
	int x = 0, f = 0;
	char ch = getchar();
	while (!isdigit(ch))f |= (ch == '-'), ch = getchar();
	while (isdigit(ch))x = (x << 1) + (x << 3) + (ch & 15), ch = getchar();
	return f ? -x : x;
}

const int Big_B = 10;
const int Big_L = 1;
inline int intcmp_ (int a, int b) {
	if (a > b) return 1;
	return a < b ? -1 : 0;
}
struct Int {
#define rg register
	inline int max (int a, int b) {
		return a > b ? a : b;
	}
	inline int min (int a, int b) {
		return a < b ? a : b;
	}
	std :: vector <int> c;
	Int () {}
	Int (int x) {
		for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
	}
	Int (LL x) {
		for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
	}
	inline void CrZ () {
		for (; !c.empty () && c.back () == 0; c.pop_back ());
	}
	inline Int &operator += (const Int &rhs) {
		c.resize (max (c.size (), rhs.c.size ()));
		rg int i, t = 0, S;
		for (i = 0, S = rhs.c.size (); i < S; ++ i)
			c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
		for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
			c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
		if (t) c.push_back (t);
		return *this;
	}
	inline Int &operator -= (const Int &rhs) {
		c.resize (max (c.size (), rhs.c.size ()));
		rg int i, t = 0, S;
		for (i = 0, S = rhs.c.size (); i < S; ++ i)
			c[i] -= rhs.c[i] + t, t = c[i] < 0, c[i] += Big_B & (-t);
		for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
			c[i] -= t, t = c[i] < 0, c[i] += Big_B & (-t);
		CrZ ();
		return *this;
	}
	inline Int &operator *= (const Int &rhs) {
		rg int na = c.size (), i, j, S, ai;
		c.resize (na + rhs.c.size ());
		LL t;
		for (i = na - 1; i >= 0; -- i) {
			ai = c[i], t = 0, c[i] = 0;
			for (j = 0, S = rhs.c.size (); j < S; ++ j) {
				t += c[i + j] + (LL) ai * rhs.c[j];
				c[i + j] = t % Big_B, t /= Big_B;
			}
			for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j)
				t += c[i + j], c[i + j] = t % Big_B, t /= Big_B;
			assert (t == 0);
		}
		CrZ ();
		return *this;
	}
	inline Int &operator /= (const Int &rhs) {
		return *this = div (rhs);
	}
	inline Int &operator %= (const Int &rhs) {
		return div (rhs), *this;
	}
	inline Int &shlb (int l = 1) {
		if (c.empty ()) return *this;
		c.resize (c.size () + l);
		rg int i;
		for (i = c.size () - 1; i >= l; -- i) c[i] = c[i - l];
		for (i = 0; i < l; ++ i) c[i] = 0;
		return *this;
	}
	inline Int &shrb (int l = 1) {
		for (rg int i = 0; i < c.size () - l; ++ i) c[i] = c[i + l];
		c.resize (max (c.size () - l, 0));
		return *this;
	}
	inline Int div (const Int &rhs) {
		assert (!rhs.c.empty ());
		Int q, r;
		rg int i;
		if (rhs > *this) return 0;
		q.c.resize (c.size () - rhs.c.size () + 1);
		rg int _l, _r, mid;
		for (i = c.size () - 1; i > c.size () - rhs.c.size (); -- i) r.shlb (), r += c[i];
		for (i = c.size () - rhs.c.size (); i >= 0; -- i) {
			r.shlb ();
			r += c[i];
			if (r.Comp (rhs) < 0) q.c[i] = 0;
			else {
				_l = 0, _r = Big_B;
				for (; _l != _r; ) {
					mid = _l + _r >> 1;
					if ((rhs * mid).Comp (r) <= 0) _l = mid + 1;
					else _r = mid;
				}
				q.c[i] = _l - 1, r -= rhs * q.c[i];
			}
		}
		q.CrZ (), *this = r;
		return q;
	}
	inline int Comp (const Int &rhs) const {
		if (c.size () != rhs.c.size ()) return intcmp_ (c.size (), rhs.c.size ());
		for (rg int i = c.size () - 1; i >= 0; -- i)
			if (c[i] != rhs.c[i]) return intcmp_ (c[i], rhs.c[i]);
		return 0;
	}
	friend inline Int operator + (const Int &lhs, const Int &rhs) {
		Int res = lhs;
		return res += rhs;
	}
	inline friend Int operator - (const Int &lhs, const Int &rhs) {
		if (lhs < rhs) {
			putchar ('-');
			Int res = rhs;
			return res -= lhs;
		} else {
			Int res = lhs;
			return res -= rhs;
		}
	}
	friend inline Int operator * (const Int &lhs, const Int &rhs) {
		Int res = lhs;
		return res *= rhs;
	}
	friend inline Int operator / (const Int &lhs, const Int &rhs) {
		Int res = lhs;
		return res.div (rhs);
	}
	friend inline Int operator % (const Int &lhs, const Int &rhs) {
		Int res = lhs;
		return res.div (rhs), res;
	}
	friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs) {
		if (rhs.c.size () == 0) out << "0";
		else {
			out << rhs.c.back ();
			for (rg int i = rhs.c.size () - 2; i >= 0; -- i)
				out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i];
		}
		return out;
	}
	friend inline std :: istream &operator >> (std :: istream &in, Int &rhs) {
		static char s[100000];
		in >> s + 1;
		int Len = strlen (s + 1);
		int v = 0;
		LL r = 0, p = 1;
		for (rg int i = Len; i >= 1; -- i) {
			++ v;
			r = r + (s[i] - '0') * p, p *= 10;
			if (v == Big_L) rhs.c.push_back (r), r = 0, v = 0, p = 1;
		}
		if (v != 0) rhs.c.push_back (r);
		return in;
	}
	friend inline bool operator < (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) < 0;
	}
	friend inline bool operator <= (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) <= 0;
	}
	friend inline bool operator > (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) > 0;
	}
	friend inline bool operator >= (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) >= 0;
	}
	friend inline bool operator == (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) == 0;
	}
	friend inline bool operator != (const Int &lhs, const Int &rhs) {
		return lhs.Comp (rhs) != 0;
	}
#undef rg
};

int n, m;
Int fac[N];

Int Pow(Int a, int b) {
	Int res = 1;
	while (b) {
		if (b & 1) res *= a;
		b >>= 1;
		a *= a;
	}
	return res;
}

Int A(int n, int m) {
	if(m>n) return 0;
	return fac[n] / fac[n - m];
}
Int C(int n, int m) {
	if(m>n) return 0;
	return fac[n] / (fac[n - m] * fac[m]);
}

signed main() {
	n = read(), m = read();
	fac[0] = 1;
	for (int i = 1; i <= n + 5; i++) fac[i] = fac[i - 1] * i;
	Int Ans;
	Ans = (A(n + 2, n + 2) * A(m, m) * C(n + 3, m));
	Ans -= (A(2, 2) * A(n + 1, n + 1) * A(m, m) * C(n + 2, m));
	return cout << Ans, 0;
}

P1763 埃及分数

迭代加深搜索。

剪枝条件:剩下分数是 \(\frac{x}{y}\) ,剩下层数是 \(dep\) ,如果这些数就算平分了也比前面的 \(Ans\) 大,就不用搜下去了。还有就是,搜索范围不能超过剩下的平均数。搞一搞就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

bool flg;
int Ans[N],T[N],Max,Lim,Zi,Mu;

void dfs(int dep,int a,int b,int pre){
	if(dep==Lim+1){
		if(!a){
			flg=1;
			if(Ans[Lim]<T[Lim]){
				for(int i=1;i<=Lim;i++) T[i]=Ans[i];
				Max=Ans[Lim];
			}
		}
		return;
	}
	if(b*(Lim+1-dep)/a>Max||Ans[dep]>Max) return;
	for(int i=max(pre,b/a);i<=b*(Lim+1-dep)/a;i++)
		Ans[dep]=i,dfs(dep+1,a*i-b,b*i,i+1);
}

signed main() {
	Zi=read(),Mu=read();
	for(Lim=1;;Lim++){
		T[Lim]=INF;
		Max=INF;
		dfs(1,Zi,Mu,1);
		if(flg) break;
	}
	for(int i=1;i<=Lim;i++) cout<<T[i]<<" ";
	return 0;
}

P4799 [CEOI2015 Day2] 世界冰球锦标赛

折半搜索板子,寄吧不是没开 128 就是数组开小就是 TLE,真拉啊。

就是把数组锯开,前后各算一部分,合起来,复杂度 \(O(2^{\frac{n}{2}})\)

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define LL __int128
#define int __int128

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

LL n,m,mid,a[N],Ans;
vector<int>s1,s2;

void dfs1(int pos,int cost){
	if(cost>m) return;
	if(pos>mid) return s1.push_back(cost),void();
	dfs1(pos+1,cost+a[pos]);
	dfs1(pos+1,cost);
}

void dfs2(int pos,int cost){
	if(cost>m) return;
	if(pos>n) return s2.push_back(cost),void();
	dfs2(pos+1,cost+a[pos]);
	dfs2(pos+1,cost);
}

void print(LL x){
	if(x>9) print(x/10);
	putchar(x%10+'0');
}

signed main() {
	n=read(),m=read();mid=(n+1)/2;
	for(int i=1;i<=n;i++)a[i]=read();
	sort(a+1,a+n+1);
	dfs1(1,0);dfs2(mid+1,0);
	sort(s2.begin(),s2.end());
	for(auto &Jb:s1) Ans+=upper_bound(s2.begin(),s2.end(),m-Jb)-s2.begin();
	print(Ans);
	return 0;
}

SP29461 AROPE3 - Alphabetic Rope3

随手切平衡树,看出来这俩傻逼操作其实就是翻转,一操作就是转 \(1\)\(l-1\),然后转 \(1\)\(r\);二操作就是转 \(r+1\)\(n\)\(l\)\(n\)。文艺平衡树搞一下就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define lson(pos) tree[pos].l
#define rson(pos) tree[pos].r
#define debug cout<<"Szt ak ioi\n";
//#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

namespace FHQ{
	int root,idx;
	struct node{int l,r,Size,val,lazy,Rand;}tree[N];
	
	int new_node(int val){tree[++idx]=(node){0,0,1,val,0,rand()};return idx;}
	
	void push_up(int pos){tree[pos].Size=tree[lson(pos)].Size+tree[rson(pos)].Size+1;}
	
	void push_down(int pos){
		if(!tree[pos].lazy) return;swap(lson(pos),rson(pos));
		tree[lson(pos)].lazy^=1,tree[rson(pos)].lazy^=1;tree[pos].lazy=0;
	}
	
	void split(int pos,int Size,int &x,int &y){
		if(!pos) return x=y=0,void();push_down(pos);
		if(tree[lson(pos)].Size+1<=Size) x=pos,split(tree[pos].r,Size-tree[lson(pos)].Size-1,tree[pos].r,y);
		else y=pos,split(tree[pos].l,Size,x,tree[pos].l);push_up(pos);
	}
	
	int merge(int x,int y){
		if(!x||!y) return x|y;
		if(tree[x].Rand<=tree[y].Rand){push_down(x),rson(x)=merge(rson(x),y);push_up(x);return x;}
		else {push_down(y);lson(y)=merge(x,lson(y));push_up(y);return y;}
	}
	
	void reverse(int l,int r){
		int x,y,z;if(l>r)return;
		split(root,l-1,x,y);split(y,r-l+1,y,z);
		tree[y].lazy^=1;root=merge(merge(x,y),z);
	}
	
	void Print(int pos){
		if(!pos)return;push_down(pos);
		Print(tree[pos].l);putchar(tree[pos].val);Print(tree[pos].r);
	}
}

int n;
char ch[N];

signed main() {
	srand(time(0));
	cin>>ch+1;int len=strlen(ch+1);
	n=read();
	for(int i=1;i<=len;i++) FHQ::root=FHQ::merge(FHQ::root,FHQ::new_node(ch[i]));
	for(int i=1;i<=n;i++){
		int opt=read();
		if(opt==1){
			int l=read()+1,r=read()+1;
			FHQ::reverse(1,l-1),FHQ::reverse(1,r);
		} else if(opt==2){
			int l=read()+1,r=read()+1;
			FHQ::reverse(r+1,len),FHQ::reverse(l,len);
		}else{
			int pos=read()+1,x,y,z;
			FHQ::split(FHQ::root,pos-1,x,y);
			FHQ::split(y,1,y,z);
			putchar(FHQ::tree[y].val);puts("");
			FHQ::root=FHQ::merge(FHQ::merge(x,y),z);
		}
//		FHQ::Print(FHQ::root);puts("");
	}
	return 0;
}

SP4491 PGCD - Primes in GCD Table

平凡莫反题,随手化一下就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
//#define int long long
const int N=1e7+7;
const int M=1e7+10;
using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}

int mu[M],prime[M],sum[M],f[M],sc;
bool vis[M];

void Mu(){
	vis[1]=mu[1]=1;
	for(int i=2;i<=N;i++){
		if(!vis[i]) prime[++sc]=i,mu[i]=-1;
		for(int j=1;j<=sc&&i*prime[j]<=N;j++){
			vis[i*prime[j]]=1;
			if(!(i%prime[j])){
				mu[i*prime[j]]=0;
				break;
			}
			mu[i*prime[j]]=-mu[i];
		}
	}
	for(int i=1;i<=sc;i++)
	for(int j=1;prime[i]*j<=N;j++)
	f[prime[i]*j]+=mu[j];
	for(int i=1;i<=N;i++) sum[i]=sum[i-1]+f[i];
}

void Main(){
	int n=read(),m=read();
	if(n>m) swap(n,m);
	int l=1,r;
	long long Ans=0;
	while(l<=n){
		r=min(n/(n/l),m/(m/l));
		Ans+=1LL*(n/l)*(m/l)*(sum[r]-sum[l-1]);
		l=r+1;
	}
	printf("%lld\n",Ans);
}

signed main() {
	Mu();int T=read();
	while(T--)Main();
	return 0;
}

今天好像还可以,但是??再接再厉吧。

posted @ 2022-08-03 22:17  Gym_nastics  阅读(27)  评论(0编辑  收藏  举报