模拟赛4

居然神奇般地没有考暴搜...啊不,\(1Liu\)大佬T1暴搜比我状压强(😭

T1:The Prices

一眼状压,然后式子推了一个小时死活推不对,就跳过直接去看T3了,最后又花半个小时搞这玩意儿,终于过了样例。

最后挂成55分(

主要的转移方程即 \(f[i][j|(1<<(k-1))]=min(f[i][j|(1<<(k-1))],f[i][j]+c[i][k])\) 但是有几个细节需要维护,首先已经转移过了的j就不需要转移了,当\(j\)与上\((1<<(k-1))\)不为0时要\(continue\),其次,对于这一个商店,每个状态需要从上一个商店加上路费转移过来,最后比较这个状态是否比上一个状态小。

感谢\(kiritokazuto\)大佬%%%

#include <bits/stdc++.h>
using namespace std;
const int maxn=100010,maxm=1010;
//目测状压 
//调了一个半小时草 
//写挂了... 
int n,m,ans=2147483645;
int c[maxm][20],d[maxm];
int f[120][(1<<16)+100];
inline int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s*w;
}
int main(){
	freopen("prices.in","r",stdin);
	freopen("prices.out","w",stdout);
	n=read();m=read();
	int Max=(1<<m)-1;
	for(int i=1;i<=n;++i){
		d[i]=read();
		for(int j=1;j<=m;++j) c[i][j]=read();
	}
	memset(f,0x7f,sizeof(f));
	f[0][0]=0;
	for(int i=1;i<=n;++i){
		for(int j=0;j<=Max;++j) f[i][j]=f[i-1][j]+d[i];
		//加上路费 
		for(int k=1;k<=m;++k){
			for(int j=0;j<=Max;++j){
				if(j&(1<<k-1)) continue;
				//如果已经转移过了就跳过 
				f[i][j|(1<<(k-1))]=min(f[i][j|(1<<(k-1))],f[i][j]+c[i][k]);
			}
		}
		for(int j=0;j<=Max;j++) f[i][j]=min(f[i-1][j],f[i][j]);
		//可以不买直接从上一个商店转移 
	}

	printf("%d",f[n][Max]); 
	return 0;
} 

T2:上白泽慧音

裸的强连通(

T3:最大公约数和最小公倍数问题

显然\(y%x\)不为0或\(y<x\)则直接输出\(0\)\(y=x\)时输出\(1\)。于是我们就能找到一些性质,即两个数除以最大公约数后的数必须互质,可以先让\(y\div x\),然后拆分出pr个素数,一个数可以选很多个,最后加起来就变成:\(C(pr,0)+C(pr,1)+C(pr,2)...+C(pr,pr)=pow(2,n)\)。蓝书里有详细证明。

我写完了。

posted @ 2022-05-24 19:00  Broken_Eclipse  阅读(41)  评论(1)    收藏  举报

Loading