1. 程式人生 > 其它 >noip模擬42(待補)

noip模擬42(待補)

A. 卷

樹形\(dp\),用對數輔助取模權值的比較.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register ll 
	#define lf double
	#define lbt(x) (x&(-x))
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=2e5+51,mod=1e9+7;
ll n,ts;
ll head[N],val[N];
struct I { lf lg; ll w=1,vis; } f[N][2];
struct II { ll u,v,nxt; } e[N<<1];
inline I getmax(I i,I j){ return i.lg>j.lg ? i : j ; }
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u],
	head[u]=ts;
}
I dfs(ll now,ll dad,bool can){
	I temp;
	if(can){
		if(f[now][1].vis) return getmax(f[now][0],f[now][1]);
		f[now][1].lg=log(val[now]),f[now][1].w=val[now],f[now][1].vis=1;
		for(re i=head[now];i;i=e[i].nxt){
			if(e[i].v==dad) continue;
			temp=dfs(e[i].v,now,0);
			f[now][1].lg+=temp.lg,(f[now][1].w*=temp.w)%=mod;
		}
		if(!f[now][0].vis){
			f[now][0].lg=0,f[now][0].w=1,f[now][0].vis=1;
			for(re i=head[now];i;i=e[i].nxt){
				if(e[i].v==dad) continue;
				temp=dfs(e[i].v,now,1);
				f[now][0].lg+=temp.lg,(f[now][0].w*=temp.w)%=mod;
			}
		}
		return getmax(f[now][0],f[now][1]);
	}
	else{
		if(f[now][0].vis) return f[now][0];
		f[now][0].lg=0,f[now][0].w=1,f[now][0].vis=1;
		for(re i=head[now];i;i=e[i].nxt){
			if(e[i].v==dad) continue;
			temp=dfs(e[i].v,now,1);
			f[now][0].lg+=temp.lg,(f[now][0].w*=temp.w)%=mod;
		}
		return f[now][0];
	}
}
signed main(){
	n=read(); ll u,v;
	for(re i=1;i<=n;++i) val[i]=read();
	for(re i=2;i<=n;++i) u=read(),v=read(),add(u,v),add(v,u);
	printf("%lld",dfs(1,0,1).w%mod);
	return 0;
}

B. 簡單題

一道確實很簡單的題..
友情提醒,以後遇到\(1\)左移多少位的數,一定要記得看範圍,看是否寫成\(1ll<<x\)..
能用快速冪儘量用快速冪,因為這個更保險,但是要注意時間.
考場程式碼加了\(ll\)就切了,懶得寫題解了.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register ll
	#define ull unsigned ll
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memcpy(x,y,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=801;
const ll mod=10000019;

ll m,n,Q,bss,lmt,r,ans,sp=1;
ll add[mod+10];
ll f[N][2];
inline ll ksm(ll a,ll b,ll c){
	a%=c; ll temp=1;
	while(b){
		if(b&1) temp=(temp*a)%c;
		a=(a*a)%c; b>>=1;
	}
	return temp%c;
}
inline void Pre(){
	add[0]=1;
	for(ll i=1;i<=mod;i++)
		add[i]=(add[i-1]*i)%mod;
}
inline ll C(ll a,ll b){
	if(a>b) return 0; if(!a) return 1;
	return (add[b]*ksm(add[a],mod-2,mod)%mod)*ksm(add[b-a],mod-2,mod)%mod;
}
ll lucas(ll a,ll b){
	if(!a) return 1;
	return C(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
signed main(){
	n=read(),Q=read(); Pre();
	ll temp=0,temp1=0,temp2=0,temp3=0,c=0;
	for(ll i=log2(n);i>=0;i--){
		c=n/(1ll<<i),c=(c+1)>>1ll; // 有 C 個奇數可以滿足   去重
		temp3=c,c-=temp,temp=temp3;
		temp1=i>>1ll,temp2=(i+1)>>1ll;
		if(temp1==temp2) (f[temp2+1][1]+=c)%=mod;
		else (f[temp2][0]+=c)%=mod;
	}
	for(re i=1;i<=log2(n);i++){
		(bss+=(f[i][0]*i%mod+f[i+1][1]*i%mod)%mod)%=mod;
		sp=(sp*(ksm(2,f[i][0],mod)%mod))%mod;
	}
	lmt=n-bss,r=lmt-bss;
	while(Q--){
		m=read(); 
		if(m<bss or m>lmt) { puts("0"); continue; }
		ans=sp*lucas(m-bss,r)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}

C. 粉絲

計數常用的兩種\(dp\),在這道題種被用得活靈活現.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register ll 
	#define lf double
	#define lbt(x) (x&(-x))
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=1e5+51;

ll m,n,l,r,mod;
ll f[N],g[N],sum[N];
inline ll Work(ll x){
	if(x>n) return 0;
	Fill(f,0),Fill(g,0),Fill(sum,0);
	ll B=sqrt(n); B=max(B,x);
	f[0]=1,g[0]=1,sum[0]=1;
	for(re i=x;i<B;i++)
		for(re j=i;j<=n;j++)
			f[j]=(f[j]+f[j-i])%mod;
	ll temp,ans=0;
	for(re i=1;i<=n/B;i++){
		temp=i*B;
		for(re j=i;j<=n-temp;j++) g[j]=(g[j]+g[j-i])%mod;
		for(re j=0;j<=n-temp;j++) sum[j+temp]=(sum[j+temp]+g[j])%mod;
	}
	for(re i=0;i<=n;i++)
		(ans+=sum[n-i]*f[i]%mod)%=mod;
	return ans;
}
signed main(){
	l=read(),r=read(),n=read(),mod=read();
	printf("%lld",(Work(l)-Work(r+1)+mod)%mod);
	return 0;
}

D. 字串