模拟赛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)\)。蓝书里有详细证明。
我写完了。

浙公网安备 33010602011771号