K. Supreme Number
期望难度:easy
考虑到答案中任意一位都必须是1或质数,可知答案只可能由1、2、3、5、7构成。由于任意两个不为1的数字构成 的两位数一定可以被11整除,所以答案中除1外的数字只能出现一次;1最多出现2次,因为111可以被3整除;而 2、5、7三者一定不会有两者同时出现。因此满足条件的整数不会超过四位,全部预处理出来即可
可以推出一共一下几个数字
1 2 3 5 7 11 13 17 23 31 37 53 71 73 113 131 137 173 311 317
然后开始查询就好了
Code就不贴了
D. Made In Heaven
期望难度:easy K短路模板题。由于数据均为随机生成,直接预处理出每个点到终点的最短路后A*搜索即可。
贴一个蔡队的代码。。(自己太菜了-.-)
code:
#include
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define X first
#define Y second
#define fastin \
ios_base::sync_with_stdio(0); \
cin.tie(0);
typedef long long ll;
typedef long double ld;
typedef pair PII;
typedef vector VI;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int maxn = 1 << 10;
vector G[maxn], rG[maxn];
inline void init(int n)
{
for (int i = 0; i < n; i++)
{
G[i].clear();
rG[i].clear();
}
}
inline void add_edge(int u, int v, int w)
{
G[u].pb(mp(v, w));
rG[v].pb(mp(u, w));
}
int d[maxn];
bool inq[maxn];
void spfa(int s)
{
clr(d, 0x3f);
clr(inq, 0);
d[s] = 0;
queue q;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
inq[u] = 0;
for (int i = 0; i < rG[u].size(); i++)
{
PII& e = rG[u][i];
int v = e.X, w = e.Y;
if (d[v] > d[u] + w)
{
d[v] = d[u] + w;
inq[v] = 1;
q.push(v);
}
}
}
}
struct HeapNode
{
int v;
ll g, f;
HeapNode(int v, ll g, ll f) : v(v), g(g), f(f) {}
bool operator<(const HeapNode& rhs) const
{
return rhs.f < f || (rhs.f == f && rhs.g < g);
}
};
bool A_star(int s, int t, int k, int tt)
{
if (s == t) k++;
if (d[s] == INF) return false;
priority_queue q;
int cnt = 0;
q.push(HeapNode(s, 0, d[s]));
while (!q.empty())
{
HeapNode tmp = q.top();
q.pop();
int u = tmp.v;
ll g = tmp.g;
if (u == t) cnt++;
if (cnt == k) return tmp.g <= tt;
for (int i = 0; i < G[u].size(); i++)
{
PII& e = G[u][i];
int v = e.X, w = e.Y;
q.push(HeapNode(v, g + w, g + w + d[v]));
}
}
return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
int n, m;
while (~scanf("%d%d", &n, &m))
{
init(n);
int s, t, k, tt;
scanf("%d%d%d%d", &s, &t, &k, &tt);
s--, t--;
while (m--)
{
static int u, v, w;
scanf("%d%d%d", &u, &v, &w);
u--, v--;
add_edge(u, v, w);
}
spfa(t);
if (A_star(s, t, k, tt))
puts("yareyaredawa");
else
puts("Whitesnake!");
}
return 0;
}
A. Gudako and Ritsuka
期望难度:Medium
考虑从后往前进行博弈动态规划,在这一过程中维护所有的先手必胜区间。区间不妨采用左开右闭,方便转移。
考虑一次转移,如果当前Servant的后一个位置属于对手,则当前Servant的必胜区间可以通过将后一个Servant的 每个必败区间的左端点+1、右端点+x得到;如果后一个位置属于自己,则可以通过将后一个Servant的必胜区间做 同样的操作得到。不妨分别对必胜区间左右端点维护一个偏移量,需要从对手进行转移时只需修改偏移量后交换左 右端点的集合,然后再在左端点的集合里插入一个0即可。
需要注意的是,这样得到的必胜区间会有重叠,可能导致对下一个对手的必胜区间的统计出错。考虑到每次转移时 所有的同类区间的长度的变化量都相同,可以分别用两个优先队列维护这两类区间,每次转移后暴力合并重叠的区 间即可。
F. Fantastic Graph
期望难度:easy
添加源点s,汇点t。 对于原图的边,定义流量为[0,1],s对于N个点都连边,流量为[L,R],M个点对t都连边,流量为 [L,R]。那么就变成了有源汇上下界可行流问题。根据相关方法建图即可。