2020牛客暑期多校训练营(第九场)
AEFIK
A. Groundhog and 2-Power Representation
题意
一个数可以由2x1+2x2+2x3+.....组成,例如1315=210+28+25+2+1=2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0).
现在给出一个由2的次幂组成的表达式,输出这个数是多少。
题解
不得不说py真的强,看到不到2分钟就有人a了,还以为是原题,赛后发现py三行。(暴风哭泣
我队用的c++高精度模拟写的,队友%%%
代码
py
1 n = input() 2 n = n.replace("(","**(") 3 print(eval(n))
c++
1 #include<bits/stdc++.h> 2 #define pb push_back 3 using namespace std; 4 typedef long long ll; 5 const int inf = 0x3f3f3f3f; 6 const ll INF = 0x3f3f3f3f3f3f3f3f; 7 const int maxn = 3e4+10; 8 9 vector<int> mult(vector<int>x,vector<int>y)//高精*高精 10 { 11 int xlen=(int)x.size(),ylen=(int)y.size(),zlen=xlen+ylen; 12 vector<int>z(zlen); 13 for(register int i=0;i<xlen;i++) 14 for(register int j=0;j<ylen;j++) 15 z[i+j]+=x[i]*y[j]; 16 for(register int i=0;i<zlen;i++) 17 if(z[i]>9) 18 { 19 z[i+1]+=z[i]/10; 20 z[i]%=10; 21 } 22 while(zlen>1 && !z.back()) 23 { 24 z.pop_back(); 25 zlen--; 26 } 27 return z; 28 } 29 vector<int> chu(int x,vector<int> vv) 30 { 31 bool flag=false; 32 vector<int> ans; 33 int t=0; 34 int i; 35 for (i=vv.size()-1; i>=0; i-- ) 36 { 37 t=t*10+vv[i]; 38 if(flag) 39 { 40 ans.push_back(t/x); 41 } 42 else if(t/x>0) 43 { 44 flag=true; 45 ans.push_back(t/x); 46 } 47 t=t%x; 48 } 49 return vector<int> (ans.rbegin(),ans.rend()); 50 } 51 vector<int> add(vector<int>x,vector<int>y)//高精+高精 52 { 53 int xlen=(int)x.size(),ylen=(int)y.size(),zlen=max(xlen,ylen)+1; 54 vector<int>z(zlen); 55 for(register int i=0;i<zlen;i++) 56 { 57 if(i<xlen) 58 z[i]+=x[i]; 59 if(i<ylen) 60 z[i]+=y[i]; 61 if(z[i]>9) 62 { 63 z[i+1]++; 64 z[i]-=10; 65 } 66 } 67 while(zlen>1 && !z.back()) 68 { 69 zlen--; 70 z.pop_back(); 71 } 72 return z; 73 } 74 void prin(vector<int> x) 75 { 76 int i; 77 if(x.size() == 0) 78 { 79 printf("0"); 80 } 81 for (i=x.size()-1;i>=0;i--) 82 { 83 printf("%d",x[i]); 84 } 85 printf(" "); 86 } 87 std::vector<int> qup(std::vector<int> vv) 88 { 89 std::vector<int> ans; 90 ans.pb(1); 91 std::vector<int> v; 92 std::vector<int> f; 93 f.pb(0); 94 v.pb(2); 95 while(vv.size() > 0 && *(--vv.end()) != 0) 96 { 97 if(vv[0] & 1) 98 ans = mult(v,ans); 99 vv = chu(2,vv); 100 v = mult(v,v); 101 } 102 return ans; 103 } 104 105 char a[maxn]; 106 vector<int> dg(int l,int r) 107 { 108 vector<int> ans; 109 110 if(l == r) 111 { 112 ans.pb(a[l] - '0'); 113 return ans; 114 } 115 ans.pb(0); 116 std::vector<int> temp; 117 for (int i = l; i <= r; i ++ ) 118 { 119 120 if(a[i] == '(') 121 { 122 int s= 0 ; 123 for(int j = i + 1; j <= r; j ++ ) 124 { 125 if(a[j] == '(') 126 s ++ ; 127 if(a[j] == ')') 128 { 129 if(s == 0) 130 { 131 ans = add(ans,qup(dg(i + 1, j - 1))); 132 i = j; 133 break; 134 } 135 else 136 s -- ; 137 } 138 } 139 continue; 140 } 141 if(a[i] == '+') 142 { 143 ans = add(ans,dg(i + 1,r)); 144 break; 145 } 146 else 147 { 148 if(a[i + 1] != '(') 149 { 150 temp.pb(a[i] - '0'); 151 ans = add(ans,temp); 152 } 153 continue; 154 } 155 } 156 return ans; 157 } 158 159 int main() 160 { 161 scanf("%s",a + 1); 162 int n = strlen(a + 1); 163 vector<int> ans = dg(1,n); 164 prin(ans); 165 }
E. Groundhog Chasing Death
题意
给出a,b,c,d,x,y,求∏(i=a,b)∏(j=c,d) gcd(xi,yj) modulo 998244353的结果
题解
第一想法肯定是暴力:枚举 i 和 j ,然后算出每一个 gcd(xi , yj),然后乘起来。但是数据 i 和 j 的数据范围都在1e6,这样肯定会超时,i 和 j 的范围在1e9,这样肯定是要爆long long的。那么就要想想怎么优化。
因为这是一个乘性函数,那么肯定要想到分解质因子,所以先预处理 x 的质因子,并记录每个质因子出现的次数,这样 xi 就可以由每个质因子个数再 *i 得到。枚举 xi 中因子 m 出现的次数,可以发现当 yj 小的时候,gcd(xi , yj) 主要是被 yj 的 m 个数约束,此时是一个等差数列;当 yj 大的时候,就是由 xi 约束,此时 yj 中 m 的个数是一个常数,暴力求解就好了。
由于质因子的幂很大,会爆long long,所以要用欧拉降幂,欧拉降幂是对mod-1取模(队友对mod取模debug好久
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 const ll mod = 998244353; 6 const ll md = 998244352; 7 vector<pair<ll,ll> > v; 8 9 void div(ll n) 10 { 11 v.clear(); 12 ll k = sqrt(n); 13 for (ll i = 2; i <= k; ++ i) { 14 ll cnt = 0; 15 while (n % i == 0) { 16 n /= i; 17 cnt ++; 18 } 19 v.push_back({i, cnt}); 20 } 21 if (n != 1) { 22 v.push_back({n, 1}); 23 } 24 } 25 26 ll phi(ll n) 27 { 28 ll ans = n; 29 ll k = sqrt(n); 30 for (int i = 2; i <= k; ++i) { 31 if (n % i == 0) { 32 ans = ans / i * (i - 1); 33 while (n % i == 0) n /= i; 34 } 35 } 36 if (n > 1) { 37 ans = ans / n * (n - 1); 38 } 39 return ans; 40 } 41 42 ll pow(ll a, ll b, ll p) { 43 ll res = 1; 44 while (b) { 45 if (b & 1) res = (res * a) % p; 46 a = a * a % p; 47 b >>= 1; 48 } 49 return res%p; 50 } 51 52 int main() 53 { 54 ll a, b, c, d, x, y; 55 scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &x, &y); 56 a = max(1LL, a); 57 c = max(1LL, c); 58 --c; 59 div(x); 60 ll ans = 1; 61 for (int i = 0; i < (int)v.size(); ++ i) { 62 ll cnt = 0; 63 while (y % v[i].first == 0) { 64 y /= v[i].first; 65 ++ cnt; 66 } 67 ll sum = 0; 68 if (cnt == 0) continue; 69 for (ll j = a; j <= b; ++ j) { 70 ll e = v[i].second * (ll)j; 71 ll f = e/cnt; 72 while (cnt * f < e) { 73 ++ f; 74 } 75 if (c >= f) { 76 sum -= ((f * (f-1) / 2)% md * (cnt % md)) % md; 77 sum = (sum % md + md) % md; 78 sum -= (ll)(((c-f+1) % md) * (e % md)) % md; 79 sum = (sum % md + md) % md; 80 } 81 else { 82 sum -= ((c * (c+1) / 2) % md * (cnt % md)) % md; 83 sum = (sum % md + md) % md; 84 } 85 sum = (sum % md + md) % md; 86 if (d >= f) { 87 sum += ((f * (f-1) / 2) % md) * (cnt % md) % md; 88 sum = (sum % md + md) % md; 89 sum += (ll)(((d-f+1) % md) * (e % md)) % md; 90 sum = (sum % md + md) % md; 91 } 92 else { 93 sum += (((d * (d+1) /2) % md) * (cnt) % md) % md; 94 sum = (sum % md + md) % md; 95 } 96 } 97 sum = (sum % md + md) % md; 98 ans *= pow(v[i].first, sum, mod); 99 ans = (ans % mod + mod) % mod; 100 } 101 ans = (ans % mod + mod) % mod; 102 printf("%lld ", ans); 103 return 0; 104 }