P1012 拼数(1s 125Mb)
题目大意
设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数。
例如:n=3时,33个整数13,312,343联接成的最大整数为:34331213
又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613
分析
排序的一个方法,比较相邻两个谁在前谁在后。直接比较字典序显然不可以,我们可以比较a+b和b+a。
代码
bool cmp(string a, string b)
{
return a+b > b+a;
}
P1094 纪念品分组(1s 125Mb)
题目大意
n个纪念品,每个有一个价值。若两个纪念品价值和小于则可以和为一组,也可以一个纪念品单独一组,问组数最少是多少。
分析
贪心。对于最大的,如果不能和最小的合成一组则单独成为一组。如果可以和最小的合成一组则合成。
简单证明。加入不和最小的一个合成,若最小的和其他合成,显然交换使最小和最大合成后仍满足答案,因为对于最大的换来一个最小的,对于最大的配对的换来一个比最大小的。think hard。
代码
sort(a+1, a+n+1);
int fr = 1, tl = n, ans = n;
while(fr < tl)
{
if(a[fr] + a[tl] <= w) fr++, tl--, ans--;
else tl--;
}
P1080 国王游戏(1s 125Mb)
题目大意
一队人排成一列,每个人有ai和bi。每个人的得分是队列前面的人的ai的乘积除以自己的bi。求任意排列方法下所有人中最大得分最小是多少。
分析
题解十分详细,拜读 https://www.luogu.com.cn/blog/league/solution-p1080
P1902 虫食算 (1s 125Mb)
题目大意
分析1
可能是有点想复杂了,一开始直接暴力40分,就想优化但想偏了可能。我想的是按照最后一位不断往前搜索,写了150多行结果90分。。。
题解里两种思路。搜索的方法是基于每一位上要么(A+B)%n == C 要么 (A+B+1)%n == C,同时最高位不能有进位。还是搜排列,每搜一个字母对整个式子判断,如果字母未被使用不管,如果使用且可以剪枝就停搜。题解作者为了提高剪枝进入的时间,按照从低位到高位字母出现的顺序进行搜索。
不知为何数字从n-1到0搜比从0到n-1快不少。。。
代码1
int ab()
{
// if(al[a[n]]+al[b[n]] >= n) return 1;
for(int i = 1; i <= n; i++)
{
if(~al[a[i]] && ~al[b[i]] && ~al[c[i]])
{
if((al[a[i]]+al[b[i]])%n != al[c[i]]
&& (al[a[i]]+al[b[i]]+1)%n != al[c[i]]) return 1;
}
}
return 0;
}
void dfs(int x)
{
if(x == n+1)
{
if(check())
{
for(int i = 0; i < n; i++) printf("%d ", al[i]);
exit(0);
}
return;
}
if(ab()) return;
for(int i = n-1; i >= 0; i--) if(!vis[i])
{
al[lis[x]] = i; vis[i] = 1; // lis为从低位到高位字母出现顺序
dfs(x+1);
al[lis[x]] = -1; vis[i] = 0;
}
}
分析2
看到所谓正解高斯消元。