NOIP analog 85 (multi school 18)

preface

It seems that the person described in the background of each topic is a role in a certain film. It seems that it is very tragic (emotional).

Then I only know T1 berries. It's really miserable...

T1 berry conscience

Problem solving ideas

First, the answer is only related to the sum of \ (w \), so the problem becomes to find the size of each group and the number of corresponding schemes for a point.

In the examination room, you want to enumerate the size of the group, and then preprocess the scheme number of \ (n \) numbers divided into \ (m \) non empty sets.

At first, I thought about the partition method, which was obviously wrong. Then I tried DP calculation, and there was \ (f_{i,j}=f_{i-1,j}\times j+f_{i-1,j-1} \)

I've been thinking about the fast power of the matrix. After watching it for a long time, I found that these TM two dimensions, I'm a ghost!!

Only after the test did I know that this is the second kind of Stirling number, and then I found that this thing can calculate the value of a row or a column by NTT. I'm shallow...

The practice of official problem solving is very different. For a pair of \ (u,v \), when they are divided into a group, there will be more contribution of \ (w_u+w_v \).

Then the answer is \ (\ sum \ limits {I = 1} ^ n w_i) \ times (\; {n \ brace K} + (n-1) \ times {n-1 \ brace K} \;) \)

It is found that the following can be directly excluded:

\[\displaystyle{n \brace k}=\frac{1}{k!}\sum_{i=0}^k(-1)^i \binom{k}{i}(k-i)^n \]

Then the linear sieve of \ (\ mathcal{O}(n) \) or the fast power of \ (\ mathcal{O}(nlogn) \).

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()	
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e6+10,M=2e3+10,mod=998244353;
int n,m,ans,base,fac[N],ifac[N] ;
int power(int x,int y,int p=mod)
{
	int temp=1;
	while(y)
	{
		if(y&1) temp=temp*x%p;
		x=x*x%p; y>>=1;
	}
	return temp;
}
int C(int x,int y){return fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
int STL(int x,int y)
{
    int temp=0;
    for(int i=0,bas=1;i<=y;i++,bas=-bas) temp=(temp+bas*C(y,i)*power(y-i,x)%mod+mod)%mod;
    return temp*ifac[y]%mod; 
}
#undef int
int main()
{
	#define int long long
	freopen("ichigo.in","r",stdin); freopen("ichigo.out","w",stdout);
	n=read(); m=read(); fac[0]=ifac[0]=1;
	for(int i=1;i<=n;i++) base=(base+read())%mod,fac[i]=fac[i-1]*i%mod;
	ifac[n]=power(fac[n],mod-2); for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
	printf("%lld",base*(STL(n,m)%mod+STL(n-1,m)%mod*(n-1)%mod)%mod);
	return 0;
}

I've run out of pears

Problem solving ideas

A direct DP is the shortest time to buy \ (j \) items in \ (I \) stores before \ (f_{i,j} \).

It is found that when \ (a_i \) is not 0, the growth is exponential, so each transfer only needs \ (log \) times.

Then, handle the case where \ (a_i \) is 0, and directly maintain a prefix and binary.

There are some small details in the code implementation.

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()	
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=2e5+10;
int n,m,ans,pos,lim,f[N],pre[N];
struct Node{int a,b;}s[N];
bool comp(Node x,Node y){x.b++;y.b++;if(x.b*y.a!=y.b*x.a)return x.b*y.a<y.b*x.a;return x.b<y.b;}
#undef int
int main()
{
	#define int long long
	freopen("eriri.in","r",stdin); freopen("eriri.out","w",stdout);
	n=read(); m=read(); lim=(int)log2(m)+1; memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;i++) s[i].a=read(),s[i].b=read();
	f[0]=0; sort(s+1,s+n+1,comp); pos=n+1;
	for(int i=1;i<=n;i++) if(!s[i].a){pos=i;break;}
	for(int i=1;i<=n;i++) s[i].b+=s[i].a+1,s[i].a++;
	for(int i=pos;i<=n;i++) pre[i]=pre[i-1]+s[i].b;
	for(int i=1;i<pos;i++)
		for(int j=min(i,lim);j>=1;j--)
			if(f[j-1]<=m) f[j]=min(f[j],f[j-1]*s[i].a+s[i].b);
	for(int i=0;i<=min(n,lim);i++)
	{
		if(f[i]>m) continue;
		int l=pos,r=n,temp=-1;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(pre[mid]<=m-f[i]) temp=mid,l=mid+1;
			else r=mid-1;
		}
		ans=max(ans,i+((~temp)?temp-pos+1:0));
	}
	printf("%lld",ans); 
	return 0;
}

T3 regiment, but

Problem solving ideas

A wonderful question.

Let \ (p(i) \) represent the number of schemes for \ (i \) rockfill \ (p(i)=(2^n-1)^{\underline{i} \).

Let \ (f(n) \) represent the number of schemes that \ (n \) will fail first. Consider adding a pile of stones equal to the XOR and sum of \ (i-1 \) after \ (i-1 \).

That is \ (p(n-1) \), but if the exclusive or sum of \ (i-1 \) rockfill is already 0, it is obviously illegal and needs to be subtracted.

In another case, the XOR sum of \ (i-2 \) stones is 0, and two new piles of the same stones are added. Obviously, it is also impossible and need to be subtracted.

So there is:

\[f(i)=p(i-1)-f(i-1)-f(i-2)\times(i-1)\times(2^n-i+1) \]

Direct recursion, and then subtract the total number of schemes.

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()	
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e7+10,mod=1e9+7;
int n,p[N],p2[N],f[N];
#undef int
int main()
{
	#define int long long
	freopen("yui.in","r",stdin); freopen("yui.out","w",stdout);
	n=read(); p2[0]=1; for(int i=1;i<=n;i++) p2[i]=p2[i-1]*2%mod;
	p[0]=1; for(int i=1;i<=n;i++) p[i]=p[i-1]*(p2[n]-i)%mod;
	for(int i=3;i<=n;i++) f[i]=(p[i-1]-f[i-1]-(i-1)*f[i-2]%mod*(p2[n]-i+1)%mod+2*mod)%mod;
	printf("%lld",(p[n]-f[n]+mod)%mod);
	return 0;
}

T4 seven negative me

Problem solving ideas

The optimal strategy is that we evenly distribute all values into a complete graph, which can be proved by the adjustment method.

Then, direct enumeration is unacceptable for \ (2^n \). Consider \ (meet\;in\;the\;middle \)

So enumerate the complete graph in the front \ (\ frac{n}{2} \), and then look at its edge connection for the next \ (\ frac{n}{2} \).

After preprocessing, \ (\ frac{n}{2} \) points, the number of complete graphs contained in all point sets.

Then enumerate the point sets of the first \ (\ frac{n}{2} \) points, and then look at their union and combination of the edges of the last \ (\ frac{n}{2} \).

There seems to be a detail wrong in the code, but the wrong point is less than 20. I directly... Combination fist??

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()	
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=50;
int n,m,m1,m2,all,maxn,e[N],f[1<<20];
#undef int
int main()
{
	#define int long long
	freopen("nanami.in","r",stdin); freopen("nanami.out","w",stdout);
	n=read(); m=read(); all=read(); m1=n>>1; m2=n-m1; if(n<=20) m1=n;
	for(int i=1,x,y;i<=m;i++) x=read(),y=read(),e[x]|=1ll<<y-1,e[y]|=1ll<<x-1;
	for(int sta=1;sta<(1ll<<m1);sta++)
	{
		int sum=__builtin_popcount(sta); if(sum<=maxn) continue;
		for(int i=1;i<=m1;i++) if((sta>>i-1)&1) if((e[i]&sta)!=(sta^(1ll<<i-1))) goto X;
		maxn=max(maxn,sum);X:;
	}
	if(n<=20) printf("%.6lf",(1.0*(maxn*(maxn-1)/2))*(1.0*all)/(1.0*maxn)*(1.0*all)/(1.0*maxn)),exit(0);
	for(int sta=1;sta<(1ll<<m2);sta++)
	{
		int sum=__builtin_popcount(sta);
		for(int i=1;i<=m2;i++) if((sta>>i-1)&1) if(((e[i+m1]>>m1)&sta)!=(sta^(1ll<<i-1))) goto Y;
		f[sta]=sta; maxn=max(maxn,sum); Y:;
	}
	for(int sta=0;sta<(1ll<<m2);sta++)
	{
		int U=(1ll<<m2)-1,sum=__builtin_popcount(sta);
		for(int i=1;i<=m2;i++) if((sta>>i-1)&1) U&=e[i+m1]>>m1;
		if(!U&&sum!=1) continue; 
		for(int i=1;i<=m2;i++)
			if((((sta>>i-1)&1)^1))
				if((((e[i+m1]>>m1)&sta)==sta&&(U&(1ll<<i-1)))){if(__builtin_popcount(f[sta|(1ll<<i-1)])<sum+1) f[sta|(1ll<<i-1)]=f[sta]|(1ll<<i-1);}
				else if(__builtin_popcount(f[sta|(1ll<<i-1)])<sum) f[sta|(1ll<<i-1)]=f[sta];
	}
	for(int sta=1;sta<(1ll<<m1);sta++)
	{
		int U=(1<<m2)-1,sum=__builtin_popcount(sta);
		for(int i=1;i<=m1;i++) if((sta>>i-1)&1) if((e[i]&sta)!=(sta^(1ll<<i-1))) goto Z;
		for(int i=1;i<=m1;i++) if((sta>>i-1)&1) U&=e[i]>>m1;
		maxn=max(maxn,sum+__builtin_popcount(f[U])); Z:;
	}
	printf("%.6lf",(1.0*(maxn*(maxn-1)/2))*(1.0*all)/(1.0*maxn)*(1.0*all)/(1.0*maxn));
	return 0;
}

Posted by hannah415 on Fri, 29 Oct 2021 03:59:20 -0700