(1)题意
求一个大于等于n的整数x,满足gcd(x,sum(dig(x)) > 1,dig表示x的各个数位。
(2)思路
考虑最差是满足gcd(x,sum(dig(x)) = 2,因此不会枚举很多,直接暴力枚举即可。
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- bool check(ll x)
- {
- ll s = 0,rx = x;
- while(rx) {
- s += rx % 10;
- rx /= 10;
- }
- return __gcd(x,s) >= 2;
- }
- void solve()
- {
- ll n;
- cin >> n;
- while(n) {
- if(check(n)) break;
- n ++;
- }
- cout << n << '\n';
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- cin >> T;
- while(T --) solve();
- return 0;
- }
(1)题意
给你n个高为1,宽为w[i]的矩形,你有一个大矩型已经确定了宽为W,你需要确定最小的h满足能放入所有的高为1的矩形。
(2)思路
考虑h一定满足单调性,所以直接二分h的值即可。
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- int a[N],n,w;
- bool check(int x)
- {
- multiset<int> st;
- rep(i,1,x) st.insert(w);
- per(i,n,1) {
- auto it = st.lower_bound(a[i]);
- if(it == st.end()) return false;
- int res = *it - a[i];
- st.erase(it);
- st.insert(res);
- }
- return true;
- }
- void solve()
- {
- cin >> n >> w;
- rep(i,1,n) cin >> a[i];
- sort(a + 1,a + 1 + n);
- int l = 1,r = n;
- while(l <= r) {
- int m = (l + r) >> 1;
- if(check(m)) r = m - 1;
- else l = m + 1;
- }
- cout << l << '\n';
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- cin >> T;
- while(T --) solve();
- return 0;
- }
(1)题意
给你一条长为k的射线,有n面镜子,每次你穿过一面镜子有两种选择,一种是降低你目前的等级,然后新生成一条反方向为目前等级-1的射线,一种是直接穿过镜子,问最多会有多少条射线。
(2)思路
发现这是个计数题,因此直接考虑dp,dp[i][j]表示当前射线为i有j面镜子的方案数是多少。
转移方程:
1.若前一条是通过降级来的,则应该是dp[i - 1][n - j]这个位置来的。
2.若前一条是通过直接穿的,则应该是dp[i][j - 1]这个位置来的。
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- using i64 = long long;
-
- constexpr int P = 1e9 + 7;
- // assume -P <= x < 2P
- int Vnorm(int x) {
- if (x < 0) {
- x += P;
- }
- if (x >= P) {
- x -= P;
- }
- return x;
- }
- template<class T>
- T power(T a, i64 b) {
- T res = 1;
- for (; b; b /= 2, a *= a) {
- if (b % 2) {
- res *= a;
- }
- }
- return res;
- }
- struct Mint {
- int x;
- Mint(int x = 0) : x(Vnorm(x)) {}
- Mint(i64 x) : x(Vnorm(x % P)) {}
- int val() const {
- return x;
- }
- Mint operator-() const {
- return Mint(Vnorm(P - x));
- }
- Mint inv() const {
- assert(x != 0);
- return power(*this, P - 2);
- }
- Mint &operator*=(const Mint &rhs) {
- x = i64(x) * rhs.x % P;
- return *this;
- }
- Mint &operator+=(const Mint &rhs) {
- x = Vnorm(x + rhs.x);
- return *this;
- }
- Mint &operator-=(const Mint &rhs) {
- x = Vnorm(x - rhs.x);
- return *this;
- }
- Mint &operator/=(const Mint &rhs) {
- return *this *= rhs.inv();
- }
- friend Mint operator*(const Mint &lhs, const Mint &rhs) {
- Mint res = lhs;
- res *= rhs;
- return res;
- }
- friend Mint operator+(const Mint &lhs, const Mint &rhs) {
- Mint res = lhs;
- res += rhs;
- return res;
- }
- friend Mint operator-(const Mint &lhs, const Mint &rhs) {
- Mint res = lhs;
- res -= rhs;
- return res;
- }
- friend Mint operator/(const Mint &lhs, const Mint &rhs) {
- Mint res = lhs;
- res /= rhs;
- return res;
- }
- friend std::istream &operator>>(std::istream &is, Mint &a) {
- i64 v;
- is >> v;
- a = Mint(v);
- return is;
- }
- friend std::ostream &operator<<(std::ostream &os, const Mint &a) {
- return os << a.val();
- }
- };
-
- void solve()
- {
- int n,k;
- cin >> n >> k;
- vector
> dp(k + 1,vector(n + 1)); - rep(i,1,k) dp[i][0] = 1;
- rep(i,1,k) {
- rep(j,1,n) {
- dp[i][j] += dp[i - 1][n - j] + dp[i][j - 1];
- }
- }
- cout << dp[k][n] << '\n';
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- cin >> T;
- while(T --) solve();
- return 0;
- }
(1)题意
你有n个活动事件,m个位置,初始在0这个位置,每一次活动给出Ti,Xi,Yi表示这个活动的类型是Ti,每一次步长为Xi'(Xi = Xi'/100000),可以执行[0,Yi]次这个步长,若Ti为1或2,若Ti为1,则表示这一次会变成pos = (pos + Xi),若Ti为2,则表示这一次会变成pos = (pos * Xi), 问你最早到达[1,m]每一个位置是第几个活动事件。
(2)思路
直接暴力即可,记Ans[i]表示到第i个位置的最早时间,若这个位置被走过了则时间可以不执行了,若当前位置已经跳出m了,则也不执行了。
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- int Ans[N];
- const int inf = 0x3f3f3f3f;
- void solve()
- {
- int n,m;
- cin >> n >> m;
- rep(i,1,m) Ans[i] = inf;
- rep(i,1,n) {
- ll t,x,y;
- cin >> t >> x >> y;
- per(j,m,0) {
- if(Ans[j] == inf) continue;
- ll p = j;
- rep(k,1,y) {
- if(t == 1) p = p + (99999 + x) / 100000;
- else p = (p * x + 99999) / 100000;
- if(p > m) break;
- if(Ans[p] < inf) break;
- Ans[p] = i;
- }
- }
- }
- rep(i,1,m) {
- if(Ans[i] == inf) cout << -1 << ' ';
- else cout << Ans[i] << ' ';
- }
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- // cin >> T;
- while(T --) solve();
- return 0;
- }
(1)题意
(2)思路
考虑这个图是一个竞赛图,我们可以直接用竞赛图解,对于一个竞赛图若按照点的出度进行排序,缩点后前面的点必定向后面所有点右边,若某一个位置前面的点的出度和为i * (i - 1) / 2,说明前面必定出现了SCC,如果前面j个点也出现了这个情况,说明要么前i个点存在两个SCC,要么后面这个不存在SCC,证明可得后面这个也一定是SCC。那么我们只需要挑一个最大的SCC的|Ka-Kb|即可。
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- PII e[N];
- void solve()
- {
- int n;
- cin >> n;
- rep(i,1,n) {
- cin >> e[i].fi;
- e[i].se = i;
- }
- stable_sort(e + 1,e + 1 + n);
- int v = 0,mx = -1,lst = 0;
- PII Ans = {0,0};
- rep(i,1,n) {
- v += e[i].fi;
- if(v == i * (i - 1) / 2) {
- if(lst != i - 1) {
- int rs = e[i].fi - e[lst + 1].fi;
- if(rs > mx) {
- Ans = {e[lst + 1].se,e[i].se};
- mx = rs;
- }
- }
- lst = i;
- }
- }
- cout << "! " << Ans.fi << ' ' << Ans.se << endl;
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- // cin >> T;
- while(T --) solve();
- return 0;
- }
(1)题意
Alice和Bob在一颗树上玩游戏,第i个节点有a[i]个石头,每轮可以选择一个距离根深度至少为k的点往上移动任意石头,问对每个节点作为根最后谁会赢。
(2)思路
对于k为1,无非就是一个树上阶梯尼姆博弈
对于k为d,我们猜测会是一个dep/d的树上阶梯尼姆博弈
因此我们考虑dp[i][j][k]表示在第i个点,距离i为j的,奇偶性为k的贡献是多少。
1.对于j < k的奇偶性不会发生变化
dp[x][i][j] ^= dp[y][i - 1][j]
2.对于j == k的会发生变化因此特殊转移就行。
dp[x][0][j] ^= dp[y][k - 1][j ^ 1]
剩下的其他根换根dp一下就可以
(3)代码
- #include
- #define rep(i,z,n) for(int i = z;i <= n; i++)
- #define per(i,n,z) for(int i = n;i >= z; i--)
- #define PII pair
- #define fi first
- #define se second
- #define vi vector
- #define vl vector
- #define pb push_back
- #define sz(x) (int)x.size()
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ll = long long;
- const int N = 1e5 + 10;
- vector<int> e[N];
- int dp[N][21][2],Ans[N],a[N];
- int n,k;
- inline void do_dp(int x,int y)
- {
- rep(i,1,k - 1) {
- rep(j,0,1) {
- dp[x][i][j] ^= dp[y][i - 1][j];
- }
- }
- dp[x][0][0] ^= dp[y][k - 1][1];
- dp[x][0][1] ^= dp[y][k - 1][0];
- }
- inline void dfs(int u,int f)
- {
- dp[u][0][0] = a[u];
- for(auto v : e[u]) {
- if(v == f) continue;
- dfs(v,u);
- do_dp(u,v);
- }
- }
- inline void dfs2(int u,int f)
- {
- if(f) {
- do_dp(f,u);
- do_dp(u,f);
- }
- rep(i,0,k - 1) Ans[u] ^= dp[u][i][1];
- for(auto v : e[u]) {
- if(v == f) continue;
- dfs2(v,u);
- }
- if(f) {
- do_dp(u,f);
- do_dp(f,u);
- }
- }
- void solve()
- {
- cin >> n >> k;
- rep(i,2,n) {
- int u,v;
- cin >> u >> v;
- e[u].pb(v),e[v].pb(u);
- }
- rep(i,1,n) cin >> a[i];
- dfs(1,0);
- dfs2(1,0);
- rep(i,1,n) {
- if(Ans[i]) cout << 1 << ' ';
- else cout << 0 << ' ';
- }
- }
- int main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0),cout.tie(0);
- int T = 1;
- // cin >> T;
- while(T --) solve();
- return 0;
- }