[考试总结]noip模拟52

似乎这个是一个暴力能够 \(ak\) 的比赛。。。

然后正道的光,然后把所有暴力卡没。。。

异或

这个题目还是比较水的吧。。。

考场上想了有一段时间,然后发现了这个规律:

\[f_i = f_{i-1} << 1 + 1 \]

这个下标代表的是 \(2^i\) 的前缀和。

然后就可以开始倍增。

然后就能愉快 \(AC\)

然后我们还发现这个玩意儿实质上就是这个。。。

for(register signed i=1;i<=n;i<<=1) ans += n / i;

然后不到 \(20byte\) 解决。。。



#include<bits/stdc++.h>
#define int long long
signed main()
{
	int n,ans = 0;std::cin>>n;
	for(register int i=1;i<=n;i<<=1)
		ans += n / i;
	std::cout<<ans<<std::endl;
}

赌神

考场上面盲猜了一个结论。。。

就是对面想要抹平这个序列,然后我自己的策略就是把这个玩意按比例分配,并且每次把所有钱都放完。

然后其实优先队列很快,然而被我删掉了。。。。

然后就有 \(80pts\)

但是实际上并不用排序。。。

然后很快。

\(\mathcal O(n)\)



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
	{
		register int f = 0;s = 0; register char ch = gc();
		while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
#define int long long
namespace xin
{
	const int mod = 998244353;
	int n,ans = 0;
	int temp[maxn],inv[maxn],a[maxn];
	std::priority_queue<int>q;
	
	auto ksm = [](int x,int y,int ret = 1) -> int
	{
		while(y)
		{
			if(y & 1) ret = ret * x % mod;
			x = x * x % mod; y >>= 1;
		}
		return ret;
	};
	int sum = 0;

	inline short main()
	{
		io >> n;
		try(i,1,n) io >> a[i],q.push(a[i]),sum += a[i];
		if(n == 1)
		{
			cout<<1<<endl;
			return 0;
		}
	
		inv[0] = inv[1] = 1;
		try(i,2,sum) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
		ans = 1;
		while(sum)
		{
//			try(i,1,n) cout<<a[i]<<' '; cout<<endl;	
			register int x = q.top(); q.pop();
			temp[1] = ans * x % mod * inv[sum] % mod;//,cout<<temp[i]<<' ';cout<<endl;
			ans = temp[1] * n % mod;
			q.push(x-1); sum --;
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

路径

点分治球出来每一种 \(dis\) 的数量。

然后暴力统计。

然后可以被卡到 \(30pts\)

但是数据过于垃圾!

然后可以过掉。。。。

正解我们来一个换跟 \(dp\)

然后式子中的 \(x^k\) 用斯特林展开

然后就能过了。。

常数还是挺大的。

\(nb\) 评测机跑了整整三秒。。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define int long long
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
   #define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
   #define sb(x) cout<<#x" = "<<x<<' '
   #define jb(x) cout<<#x" = "<<x<<endl
   #define debug cout<<"debug"<<endl
   #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
   char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
   class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
   {
   	register int f = 0;s = 0; register char ch = gc();
   	while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
   	while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return s = f ? -s : s,*this;
   }}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
namespace xin
{
   const int mod = 998244353;
//	const int mod = 10007;
   auto ksm = [](int x,int y,int ret = 1) -> int
   {
   	while(y)
   	{
   		if(y & 1) ret = ret * x % mod;
   		x = x * x % mod; y >>= 1;
   	}
   	return ret;
   };
   signed f1[maxn][101],f2[maxn][101];
   int C[maxn/1000][maxn/1000],temp[maxn],fac[maxn];
   int n,k;
   class xin_edge{public:int next,ver;}edge[maxn<<1];
   int head[maxn],rp;
   auto add = [](int x,int y) -> void {edge[++rp].ver = y;edge[rp].next = head[x]; head[x] = rp;};
   void dfs1(int x,int f)
   {
   	f1[x][0] = 1;
   	go(i,x)
   	{
   		if(y == f) continue;
   		dfs1(y,x);
   		try(j,1,k) (f1[x][j] += (f1[y][j] + f1[y][j-1]) % mod) %= mod;
   		(f1[x][0] += f1[y][0]) %= mod;
   	}
   }
   void dfs2(int x,int f)
   {
   	try(i,0,k) f2[x][i] = f1[x][i];

   	if(f)
   	{
   		try(i,1,k) temp[i] = (ll)(f2[f][i] - f1[x][i] + mod - f1[x][i-1] + mod) % mod;
   		temp[0] = (ll)(f2[f][0] - f1[x][0] + mod) % mod;
   		try(i,1,k) (f2[x][i] += (temp[i] + temp[i-1]) % mod) %= mod;
   		(f2[x][0] += temp[0]) %= mod;
   	}

   	go(i,x)
   	{
   		if(y == f) continue;
   		dfs2(y,x);
   	}
   }
   inline short main()
   {
   	io >> n >> k;
   	try(i,1,n-1)
   	{
   		register int x,y; io >> x >> y;
   		add(x,y); add(y,x);
   	}
   	fac[0] = 1;  try(i,1,k) fac[i] = fac[i-1] * i % mod;
   	C[0][0] = C[1][1] = 1;
   	try(i,2,k) try(j,1,i)
   		C[i][j] = (C[i-1][j] * j + C[i-1][j-1]) % mod;
   	dfs1(1,0); dfs2(1,0);
   	int ans = 0;
   	try(i,1,n)
   	{
   		try(j,0,k) (ans += C[k][j] * fac[j] % mod * f2[i][j] % mod) %= mod;
//			printf("%lld\n",ans);
   	}
   	cout<<ans * ksm(2,mod-2) % mod<<endl;
   	return 0;
   }
}
signed main() {return xin::main();}

``

# 树

对于每一个深度建一个动态开点线段树。

然后暴力跳深度。

然后就行了。

## 当然这个不是正解!!!

然后正解是树上分块。

但是挺慢的。。。

```cpp


#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
   #define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
   #define sb(x) cout<<#x" = "<<x<<' '
   #define jb(x) cout<<#x" = "<<x<<endl
   #define debug cout<<"debug"<<endl
   #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
   char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
   class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
   {
   	register int f = 0;s = 0; register char ch = gc();
   	while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
   	while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return s = f ? -s : s,*this;
   }}io;
}
using namespace xin_io;static const int maxn = 2e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
namespace xin
{
   auto max = [](int x,int y) -> int{return x > y ? x : y;};
   auto min = [](int x,int y) -> int{return x < y ? x : y;};
   int n,m,maxdep;
   class xin_edge{public:int next,ver;}edge[maxn];
   int head[maxn],rp;
   auto add = [](int x,int y) -> void {edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;};
   int d[maxn],fa[maxn],rt[maxn],id[maxn],siz[maxn],tot;
   void dfs(int x,int f)
   {
   	d[x] = d[f] + 1;  maxdep = max(d[x],maxdep);
   	id[x] = ++tot; siz[x] = 1;
   	go(i,x)
   	{
   		if(y == f) continue;
   		dfs(y,x); siz[x] += siz[y];
   	}
   }
   class xin_seg
   {
   	private:
   		#define ls(fa) (t[fa].lson)
   		#define rs(fa) (t[fa].rson)
   		std::function<void(int)> up = [&](int fa) -> void{t[fa].s = t[ls(fa)].s + t[rs(fa)].s;};
   		std::function<void(int,int,int)> down = [&](int fa,int l,int r) -> void
   		{
   			if(!t[fa].debt) return ;
   			register int mid = l + r >> 1;
   			t[ls(fa)].s += (mid - l + 1) * t[fa].debt; t[rs(fa)].s += (r - mid) * t[fa].debt;
   			t[ls(fa)].debt += t[fa].debt;  t[rs(fa)].debt += t[fa].debt;
   			t[fa].debt = 0;
   		};
   	public:	
   		class xin_tree{public:int s,lson,rson,debt;}t[maxn<<4]; int tot = 0;
   		void modify(int &fa,int l,int r)
   		{
   			if(!fa) fa = ++tot;
   			if(l == r) return ;
   			register int mid = l + r >> 1;
   			modify(ls(fa),l,mid); modify(rs(fa),mid+1,r);
   		}
   		void insert(int &fa,int l,int r,int ql,int qr,int val)
   		{
   			if(!fa) fa = ++tot;
   			if(ql <= l and qr >= r) return t[fa].s += val * (r - l + 1),t[fa].debt += val,void();
   			register int mid = l + r >> 1; down(fa,l,r);
   			if(ql <= mid) insert(ls(fa),l,mid,ql,qr,val); if(qr >  mid) insert(rs(fa),mid+1,r,ql,qr,val);
   			up(fa);
   		}
   		int query(int fa,int l,int r,int pos)
   		{
   			if(l == r) return t[fa].s;	register int mid = l + r >> 1; down(fa,l,r);
   			if(pos <= mid) return query(ls(fa),l,mid,pos); else return query(rs(fa),mid+1,r,pos);
   		}
   }t;
   inline short main()
   {
   	io >> n >> m;
   	try(i,1,n-1)
   	{
   		register int x,y; io >> x >> y;
   		add(x,y); add(y,x);
   	}
   	dfs(1,0);
   	
   
   	try(i,1,maxdep) t.modify(rt[i],1,n);
   	
   	try(que,1,m)
   	{
   		register int op; io >> op;
   		if(op == 1)
   		{
   			register int x,mod,dis,val; io >> x >> mod >> dis >> val;
   			for(register int i=d[x]+dis;i<=maxdep;i+=mod) t.insert(rt[i],1,n,id[x],id[x]+siz[x]-1,val);
   		}
   		else {register int x;io >> x; printf("%d\n",t.query(rt[d[x]],1,n,id[x]));}
   	}
   	return 0;
   }
}
signed main() {return xin::main();}

posted @ 2021-09-15 07:07  NP2Z  阅读(32)  评论(0编辑  收藏  举报