牛客IOI周赛23-普及组
A - 小L的作文
题意
给一个字符x和一个字符串b 然后去找b中x出现了几次
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; const int N = 1e5 + 7; const int INF = 0x3f3f3f3f; int main(void){ char a , b; cin>>a; getchar(); ll ans = 0; while(scanf("%c" , &b) && b != '\n'){ if(b == a) ans++; } cout<<ans<<endl; return 0; }
B - 小L的多项式
题意
简单来说就是给出一个多项式 然后给一个数字让你把这个数字带到这个多项式里求值 多项式是规律的 即这样
有多少个就有多少项(加一项,还有0次方)
并且数据范围较小 直接暴力即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } const int N = 1e5 + 7; const int INF = 0x3f3f3f3f; const int mod = 998244353; int a[N]; int main(void){ int n , m; scanf("%d" , &n); for(int i = 1 ; i <= n + 1 ; ++i){ scanf("%d" , &a[i]); } scanf("%d" , &m); ll k = 0; for(int i = 1 ; i <= m ; ++i){ ll ans = 0; scanf("%lld" , &k); for(int j = 1 ; j <= n + 1 ; ++j){ ans += a[j] * qpow(k , j - 1 , mod) % mod; ans %= mod; } printf("%lld%c" , ans , i == m ? '\n' :' '); } return 0; }
这是我比赛的时候的代码 然后还有更快的做法
即因为是不断地从一次方二次方三次方这样乘上来 因此我们可以保存上一次的结果然后用到下一次 这样就不用每次都一下了 速度会快很多
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } const int N = 1e5 + 7; const int INF = 0x3f3f3f3f; const int mod = 998244353; int a[N]; int main(void){ int n , m; scanf("%d" , &n); for(int i = 1 ; i <= n + 1 ; ++i){ scanf("%d" , &a[i]); } scanf("%d" , &m); ll k = 0; for(int i = 1 ; i <= m ; ++i){ ll ans = 0; scanf("%lld" , &k); ll t = 1; for(int j = 1 ; j <= n + 1 ; ++j){ ans += a[j] * t % mod; t = (t * k) % mod; ans %= mod; } printf("%lld%c" , ans , i == m ? '\n' :' '); } return 0; }
C - 小L的编辑器
题意
给出两个字符串a ,b,然后a中的字符按照b的规律输出,即有一个光标,每一次输出之后,光标停的位置按照b的顺序
即 a中为 ab
b为LR
那么第一次输出之后就是 |a
然后再输出b就是在a的左边
即输出之后就是 b|a
如果这个时候还是有一个c 然后对应b中是L
那么就是b|ca
到现在为止如果直接去模拟 不仅时间复杂度裂开而且挺难模拟的
我们直接观察 以光标为分界线 其实不难看出 在右边的就是谁先进来就排在后面 左边的就是谁先进来就谁排在前面 所以很明显了
当输入L的时候就把字符插到一个栈中 输入R的时候 就插到队列中 然后把栈和队列按顺序输出就好了
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; const int N = 1e5 + 7; const int INF = 0x3f3f3f3f; int main(void){ string a , b; cin>>a>>b; stack<char>st1; queue<char>st2; for(int i = 0 ; i < a.size() ; ++i){ if(b[i] == 'L'){ st1.push(a[i]); } else{ st2.push(a[i]); } } while(st2.size()){ cout<<st2.front(); st2.pop(); } while(st1.size()){ cout<<st1.top(); st1.pop(); } return 0; }
D - 小L的数列
题意
给出个数 要求从中挑出一些数来组成一个数列 要求排在前面的小于后面的并且相邻的两个数字不互质
要不互质那么我们就要求取出来的数字两个之间有相同的因子,因此我们可以先把所有的素数筛出来,然后我们去找那些数字有这个素数作为因子的,再找数字的时候 我们可以记录这个数字的下一个用相同因子的素数
我们只需要找到下一个有着相同的因子的数即可 然后进行dp
然后这个代码应该是目前最快的了
几个加速的地方 桶排 因为数据卡的很那个 所以用桶排是比直接sort要快的
然后dp的优化 因为上面也说了 我们只要把上一个和他有相同因子的转移过来就可以了
然后筛素数的时候 只需要筛到 就可以了 因为后面不会再出现这个素数的倍数了
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; const int N = 1e5 + 7; const int INF = 0x3f3f3f3f; const int maxn = 1e5 + 7; bool vis[maxn]; vector<int>prime; int i ; inline int max(int a,int b) { return a>b?a:b; } inline void initial() { for (i = 2; 2 * i < maxn ; ++i) { if (!vis[i]) prime.push_back(i); for (int j = 0,size=prime.size(); j < size; ++j) { if (i * prime[j] >= maxn) break; vis[i * prime[j]] = true; if (i % prime[j] == 0) break; } } } inline int read() { char c=getchar();int x=0;bool f=0; for(;!isdigit(c);c=getchar())f^=!(c^45); for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48); if(f)x=-x;return x; } int a[N] , dp[N] , last[N]; int main(void){ initial(); int T = read() , n , k; while(T--){ n = read(); memset(last , 0 , sizeof(last)); memset(a , 0 , sizeof(a)); for(int i = 1 ; i <= n ; ++i){ k = read(); a[k] = 1; } int m = 0; int res = 1; for(i = 2 ; i <= 100000 ; ++i){ if(a[i] == 0) continue; dp[i] = 1; int y = i; for(auto x : prime){ if(x > y) break; if(!vis[y]){ if(last[y]){ dp[i] = max(dp[i] , dp[last[y]] + 1); } last[y] = i; break; } if(y % x == 0){ if(last[x]){ dp[i] = max(dp[i] , dp[last[x]] + 1); } last[x] = i; while(y % x == 0) y /= x; } } res = max(res , dp[i]); } printf("%d\n" , res); } return 0; }