Loading

noip模拟73

A. 小L的疑惑

签到题,随便做.

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

const ll N=1e5+21;

ll m,n;
ll val[N],pre[N];
signed main(){
	File(math);
	n=read();
	for(ll i=1;i<=n;i++) val[i]=read();
	sort(val+1,val+1+n);
	for(ll i=1;i<=n;i++){
		if(val[i]>pre[i-1]+1){ printf("%lld\n",pre[i-1]+1),exit(0); }
		pre[i]=pre[i-1]+val[i];
	}
	printf("%lld\n",pre[n]+1),exit(0);
}

B. 小L的数列

签到题,矩阵乘乱写,有点卡常,可以把矩阵快速幂写成矩阵光速幂.

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

const ll N=205,mod=998244353,md=998244352;

ll m,n,ans;
ll val[N];
ll f[N][N],g[N][N],c[N][N];
auto ksm=[](ll a,ll b,ll c)->ll{
	ll res=1; a%=c; if(!a) return 0;
	for(;b;b>>=1,a=a*a%c) if(b&1) res=res*a%c;
	return res%c;
};
inline void mulself(){
	Fill(c,0);
	for(ll i=1;i<=m;i++){
		for(ll k=1;k<=m;k++){
			for(ll j=1;j<=m;j++)
				c[i][j]=(c[i][j]+g[i][k]*g[k][j])%md;
		}
	}
	Copy(g,c);
}
inline void mul(){
	Fill(c,0);
	for(ll i=1;i<=m;i++){
		for(ll k=1;k<=m;k++){
			for(ll j=1;j<=m;j++)
				c[i][j]=(c[i][j]+f[i][k]*g[k][j])%md;
		}
	}
	Copy(f,c);
}
signed main(){
	File(seq);
	n=read(),m=read(); ll a,b,c,x,y;
	for(ll i=1;i<=m;i++) g[1][i]=read(),f[i][i]=1;
	for(ll i=2;i<=m;i++) g[i][i-1]=1;
	for(ll i=1;i<=m;i++) val[i]=read()%mod;
	if(n<=m) printf("%lld\n",val[n]),exit(0);
	b=n-m,ans=1;
	for(;b;b>>=1,mulself()) if(b&1) mul();
	for(ll i=1;i<=m;i++){
		ans=ans*ksm(val[m-i+1],f[1][i],mod)%mod;
	}
	printf("%lld\n",ans),exit(0);
}

C. 连边

签到题,然而我死了..

考场上想复杂了,其实每个点到黑点的最短距离其实把所有黑点压进去跑最短路就能求了.

这个东西其实应该由自己想到,但是失败了,这个东西以后要学会.

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

const ll N=1e5+21;

ll m,n,ts=1,sum;
ll col[N],head[N],ans[N],vis[N<<2],dis[N];
queue<ll> que;
struct I { ll u,v,w,nxt; } e[N<<2];
inline void add(ll u,ll v,ll w){
	e[++ts].u=u,e[ts].v=v,e[ts].w=w;
	e[ts].nxt=head[u],head[u]=ts;
}
signed main(){
	File(minimum);
	n=read(),m=read(); ll u,v,w; Fill(dis,0x3f);
	for(ll i=1;i<=n;i++){
		if(col[i]=read()) 
			que.push(i),dis[i]=0,vis[i]=1;
	}
	for(ll i=1;i<=m;i++){
		u=read(),v=read(),w=read();
		add(u,v,w),add(v,u,w);
	}
	while(que.size()){
		u=que.front(),que.pop();
		for(ll i=head[u];i;i=e[i].nxt){
			if(dis[e[i].v]>dis[u]+e[i].w){
				dis[e[i].v]=dis[u]+e[i].w;
				ans[e[i].v]=i; 
				if(!vis[e[i].v]) que.push(e[i].v);
			}
			else if(dis[e[i].v]==dis[u]+e[i].w){
				if(e[i].w<e[ans[e[i].v]].w) ans[e[i].v]=i;
			}
		}
		vis[u]=0;
	}
	for(ll i=1;i<=n;i++){
		if(col[i]) continue;
		sum+=e[ans[i]].w*(!vis[ans[i]]);
		vis[ans[i]]=1,vis[ans[i]^1]=1;
	}
	if(not sum) puts("impossible"),exit(0);
	printf("%lld\n",sum),exit(0);
}

D. 小L的有向图

签到题,然而我又死了..

状压 \(dp\),其实状态定义就决定了自己这个题究竟能不能 \(A\) 掉.

自己一直想着 \(dp_s\) 表示 \(s\) 点集计算所有内部边的代价.

但其实如果换个状态定义,\(dp_s\) 表示 \(s\) 点集计算所有指向 \(s\) 内点的边的代价.

这样就很好做了.

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

const ll mod=998244353,N=23;

ll m,n,ts,U;
ll e[N];
ll f[1<<N],cnt[1<<N];
signed main(){
	File(topology);
	n=read(),m=read(),U=(1<<n)-1,f[0]=1; ll u,v;
	for(ll i=1;i<=m;i++)
		u=read(),v=read(),e[v]|=1<<u-1;
	for(ll i=1;i<=U;i++) cnt[i]=cnt[i&(i-1)]+1;
	for(ll i=0;i<=U;i++){
		for(ll j=1;j<=n;j++){
			if((i>>j-1)&1) continue;
			ll w=cnt[i&e[j]];
			f[i|1<<j-1]=(f[i|1<<j-1]+f[i]*(1ll<<w)%mod)%mod;
		}
	}
	printf("%lld\n",f[U]),exit(0);
}
posted @ 2021-10-10 21:43  AaMuXiiiiii  阅读(38)  评论(0)    收藏  举报