hihocoder offers8的3道题,都非常有意思。
做了2道,有一道有思路没时间补了。
-
A题
** tag**: 数论
题目链接:http://hihocoder.com/contest/offers8/problem/1
解法:
- 等价于要满足关系式 (D*i) mod L <= L-F, i为任意自然数,
- 就是要找(D*i) mod L 中最大的那个数。
- 若f(y)为 max({x|0<=x
gcd(D,L)*f(L/gcd(D,L)); - 求f(y) 可以从大到小枚举
代码:
#include
int gcd(int a, int b) {
return b?gcd(b,a%b):a;
}
bool check(int l, int f, int d) {
if(f>l) return false;
if(d==0) return false;
int gd = gcd(l, d);
l/=gd;
int i;
for(i=l-1; i>=0; --i) {
if(gcd(i,l)==1) break;
}
if(gd*i+f>gd*l) return false;
return true;
}
int main() {
int t; scanf("%d", &t);
while(t--) {
int l, f, d;
scanf("%d%d%d", &l, &f, &d);
if(check(l,f,d)) puts("YES");
else puts("NO");
}
return 0;
}
-
B题
** tag**: 并查集, 连通块
题目链接:http://hihocoder.com/contest/offers8/problem/2
解法
- 求连通块可以用并查集
- 由于列数为第一关键字,行数为第二关键字,标号要从要从左到有,再从上到下标,合并时设集合中标号最小的为代表元
- 统计的时候可以用map,因为map为平衡二叉树,遍历的时候自然有序
4,输出矩阵的时候,不在当前连通块,但在当前矩阵的不能输出
5 注意left, right, up, down, 中存在不能做变量名的,不然会WA.
代码
#include
#include
#include
-
C题
tag: dp, 可以不用树状数组
题目链接:http://hihocoder.com/contest/offers8/problem/3
解法
- n*n的方法很简单,现在针对它进行该进。
- 假设dp[i]代表前i个数的方法数
- 其实几乎前面所有的方法都可以选,但前缀和等于sum[i]的不能所以,统计前缀和为sum[i]的方法个数,设为cnt[sum[i]]
- sum[i]可能为负,可以离散化
- dp方程
total = cnt[sum[0]] = 1;
for(int i=1; i<=n; ++i) {
dp[i] = (total-cnt[sum[i]])%MOD;
cnt[sum[i]] = (cnt[sum[i]]+dp[i])%MOD;
total = (total+dp[i])%MOD;
}
- 用树状数组求total非常不好。