Denso Create Programming Contest 2022 Winter(AtCoder Beginner Contest 280)D-F
前三个题目太简单了 我就不写了
D 我的想法是分解质因数 将它分解成a1^p1 * a2 ^ p2 * a3 ^ p3的形式
那么很明显 我们假设Ni表示最小的满足能被ai^pi整除的整数 那么答案就是N = max(N1,N2....Nn)
考虑怎么计算Ni
我们将N的阶乘理解成每次加入一个末尾的数相乘 那么当每次加入的数是ai的倍数的时候 才距离我们想要的答案更进一步
所以可以直接枚举Ni为多少倍的ai 然后算能不能满足即可
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } int a[110] , cnt[110], tot; int ans ; int calc1(int x , int y){ int sum = 0 ; while(x % y == 0){ sum++ ; x /= y ; } return sum ; } int calc(int d , int p){ int sum = 0 ; for(int i = 1 ; ; i++){ sum += calc1(i * d , d) ; if(sum >= p){ return i * d ; } } } signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; int k = read() ; int mx = sqrt(k) ; for(int i = 2 ; i <= mx ; i++){ if(k % i == 0){ a[++tot] = i ; while(k % i == 0) cnt[tot]++ , k /= i ; } } if(k != 1) a[++tot] = k , cnt[tot] = 1 ; for(int i = 1 ; i <= tot ; i++){ ans = max(ans , calc(a[i] , cnt[i])) ; } printf("%lld" , ans) ; return 0 ; }
E题 经典期望题 我以前写过一个这种期望的博客 https://www.luogu.com.cn/blog/zht20040830/shi-yue-yue-sai-t2-post
其实就是直接设状态去递推就完事了 令dp[i] 为消灭i值的怪兽的期望操作数 那么每一次要么从i-1转移 要么从i-2转移
看代码就可以了
#include<bits/stdc++.h> using namespace std ; #define maxn 400100 #define int long long int read(){ int ans = 0 , f = 1 ; char ch = getchar() ; while ( !isdigit(ch) ){ if( ch == '-' ) f = -1 ; ch = getchar() ; } while ( isdigit(ch) ) ans = (ans * 10) + (ch ^ '0') , ch = getchar() ; return ans * f ; } const int mod = 998244353 ; int pac ; int p , n ; int f[maxn] ; int p1 , p2 ; int ksm(int a , int b){ int sum = 1 ; while(b){ if(b & 1) sum = sum * a % mod ; a = a * a % mod ; b >>= 1 ; } return sum ; } int findf(int x){ if(f[x]) return f[x] ; return f[x] = (findf(x - 1) * p1 % mod + findf(x - 2) * p2 % mod + 100) * pac % mod ; } signed main(){ // freopen("test.in" , "r" , stdin) ; // freopen("test.out" , "w" , stdout) ; n = read() , p = read() ; p2 = p ; p1 = 100 - p ; pac = ksm(100 , mod - 2 ) ; f[1] = 1 ; f[2] = p2 * pac % mod + 2 * p1 * pac % mod ; printf("%lld" , findf(n)) ; return 0 ; }
F题 理解题意很重要 到达目的地后是可以不用停下来的!!!!!
不一定要停下来!!!
分情况讨论
1。不能到达 那就是不在一个图里面 所以用并查集即可
2.可以到达 但是inf
很明显 如果出现了一个连通分量并且以一个点为起点 到达某一个点有两种不同的dis值 那么这种情况下肯定是inf 因为我可以一直在这个环上沿着正方向转圈圈
所以如果x和y所在图上有这样一种连通分量的存在 肯定是inf了 最后把这种集合标记一下即可
那么距离要怎么求呢
我们以这个集合的f[i] (并查集里面的概念)为起点去dfs 算dis 最后dis[y] - dis[x] 就是答案了
(还没写 因为没空 先留坑 其实是tarjan不太熟练了

浙公网安备 33010602011771号