AEFIK
A. Groundhog and 2-Power Representation
题意
一个数可以由2
x1+2
x2+2
x3+.....组成,例如1315=2
10+2
8+2
5+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 #include2 #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 ) 14 for(register int j=0;j ) 15 z[i+j]+=x[i]*y[j]; 16 for(register int i=0;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 ) 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("\n"); 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,求
\displaystyle\prod_{i=a}^b\prod_{j=c}^d\gcd(x^i,y^j)i=a∏bj=c∏dgcd(xi,yj) modulo 998244353的结果
题解
第一想法肯定是暴力:枚举 i 和 j ,然后算出每一个 gcd(x
i , y
j),然后乘起来。但是数据 i 和 j 的数据范围都在1e6,这样肯定会超时,i 和 j 的范围在1e9,这样肯定是要爆long long的。那么就要想想怎么优化。
因为这是一个乘性函数,那么肯定要想到分解质因子,所以先预处理 x 的质因子,并记录每个质因子出现的次数,这样 x
i 就可以由每个质因子个数再 *i 得到。枚举 x
i 中因子 m 出现的次数,可以发现当 y
j 小的时候,gcd(x
i , y
j) 主要是被 y
j 的 m 个数约束,此时是一个等差数列;当 y
j 大的时候,就是由 x
i 约束,此时 y
j 中 m 的个数是一个常数,暴力求解就好了。
由于质因子的幂很大,会爆long long,所以要用欧拉降幂,欧拉降幂是对mod-1取模(队友对mod取模debug好久
代码
1 #include2 using namespace std; 3 4 typedef long long ll; 5 const ll mod = 998244353; 6 const ll md = 998244352; 7 vector > 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\n", ans); 103 return 0; 104 }
F. Groundhog Looking Dowdy
题意
土拨鼠要和苹果约会,第 i 天它的第 j 件衣服的邋遢度为 a
ij ,它要在n天中选择m天和苹果约会,要求选出的m天衣服的邋遢度的最大值和最小值的差值最小。
题解
因为要最小化最大值和最小值的差值,所以用pair存每件衣服的邋遢度和第几天,然后对邋遢度从小到大排序。那么问题就转换成了求一个区间 [L,R] ,使得这个区间覆盖m个不同的天,并且R的邋遢度-L的邋遢度最小。这个问题就可以用尺取解决了。对于每一个L,求出最小的合法的R,每次更新差值最小值即可。
代码
1 #include2 #define st first 3 #define sd second 4 #define ll long long 5 #define pii pair 6 using namespace std; 7 8 const int inf = 0x3f3f3f3f; 9 const int maxn = 2e6+10; 10 11 pii pp[maxn]; 12 int vis[maxn]; 13 14 int main() 15 { 16 int n,m; 17 scanf("%d%d",&n,&m); 18 int cnt = 0; 19 for (int i = 1; i <= n; i ++ ){ 20 int p; 21 scanf("%d",&p); 22 for (int j = 1; j <= p; j ++ ){ 23 int x; 24 scanf("%d",&x); 25 pp[++cnt].st = x; 26 pp[cnt].sd = i; 27 } 28 } 29 sort(pp + 1, pp + 1 + cnt); 30 int num = 0; 31 int l = 1, r = 1; 32 int minn = pp[1].st, maxx = 0; 33 int ans = inf; 34 while(1){ 35 while(r <= cnt && num < m){ 36 if(vis[pp[r].sd] == 0) num ++ ; 37 vis[pp[r].sd] ++ ; 38 maxx = pp[r].st; 39 r ++ ; 40 } 41 if(num < m) 42 break; 43 ans = min(ans, maxx - minn); 44 vis[pp[l].sd] -- ; 45 if(vis[pp[l].sd] == 0) num -- ; 46 minn = pp[l + 1].sd; 47 l ++ ; 48 } 49 printf("%d\n",ans); 50 }
I. The Crime-solving Plan of Groundhog
题意
给出n个数(0<=a[i]<=9),由这n个数组成2个数,使得这两个数的乘积最小。
题解
自己造几个例子就可以看出,选择0之外最小的数和剩下的数字组成的没有前导0的数相乘结果最小。剩下的数字怎样最小呢,当然是找到最小的非零的数做第一位,后边接上所有的0,再按照有小到大的顺序放剩下的数字。因为n的范围在1e5,所以要用高精度乘法。
推导:
把当前的数字拆成4个数 a, b, c, d (a ≤ b ≤ c ≤ d) ,那么我们有两种决策:两位数×两位数,或者三位数×一
位数。
(10a + d) * (10b + c) = 100ab + 10ac + 10bd + cd
(100b+10c+d) * a = 100ab + 10ac +ad<(10a + d) * (10b + c)
同理,可以证明留一个最小的正整数作为第一个数,剩下的所有数字排成最小的数作为第二个数时,答案取到最小值。
代码
1 #include2 #define ll long long 3 using namespace std; 4 5 int a[100100]; 6 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 int t; 13 cin>>t; 14 while(t--){ 15 int n; 16 cin>>n; 17 for(int i=0;i >a[i]; 18 sort(a,a+n); 19 int k=0; 20 while(k 0) k++; 21 vector<int>q; 22 q.push_back(a[k+1]); 23 for(int i=0;i 0); 24 for(int i=k+2;i ) q.push_back(a[i]); 25 vector<int>ans; 26 for(int i=q.size()-1;i>=0;i--){ 27 int x=q[i]*a[k]; 28 ans.push_back(x); 29 } 30 for(int i=0;i<10;i++) ans.push_back(0); 31 for(int i=0;i ){ 32 if(ans[i]>=10){ 33 ans[i+1]+=ans[i]/10; 34 ans[i]%=10; 35 } 36 } 37 while(!ans.back()) ans.pop_back(); 38 for(int i=ans.size()-1;i>=0;i--) cout<<ans[i]; 39 cout<<endl; 40 } 41 return 0; 42 }
K. The Flee Plan of Groundhog
题意
土拨鼠在第1个宿舍,橙子在第n个宿舍。这n个宿舍间有n-1条路并且长度都为1,土拨鼠从第1个房间去第n个宿舍,速度为1m/s;橙子从第n个宿舍追赶土拨鼠,速度为2m/s。
题解
二分时间 t ,然后判断在 ts 内土拨鼠是否会被橙子追上。以橙子所在的寝室 n 为根建树,从 1 到 n 枚举所有土拨鼠能够到达的点,先找出t秒能走到哪个点,然后再找这个点能走到的离n最远的点,判断在走的过程中会不会被追上。
代码
1 #include2 using namespace std; 3 4 const int maxn = 1e5+10; 5 vector<int> vv[maxn]; 6 int vis[maxn]; 7 int f[maxn]; 8 int dep[maxn]; 9 10 void dfs(int x,int fa,int de) 11 { 12 f[x] = fa; 13 dep[x] = de; 14 for (int i =0 ; i< vv[x].size(); i ++ ) 15 { 16 int v = vv[x][i]; 17 if(v == fa) 18 continue; 19 dfs(v,x,de + 1); 20 vis[x] |= vis[v]; 21 } 22 } 23 int ans =0 ; 24 void dfs2(int x,int fa,int de) 25 { 26 ans = max(ans,de); 27 for (int i =0 ; i ) 28 { 29 int v = vv[x][i]; 30 if(v == fa) 31 continue; 32 dfs2(v,x,de + 1); 33 } 34 35 } 36 int main() 37 { 38 int n,m; 39 scanf("%d%d",&n,&m); 40 for (int i = 1; i < n; i ++ ) 41 { 42 int x,y; 43 scanf("%d%d",&x,&y); 44 vv[x].push_back(y); 45 vv[y].push_back(x); 46 } 47 vis[1] = 1; 48 dfs(n,0,1); 49 int k = -1; 50 int s = dep[1] - m; 51 for (int i = 1; i <= n; i ++ ){ 52 if(vis[i] && dep[i] == s){ 53 k = i; 54 break; 55 } 56 } 57 int num = dep[k] - 1; 58 dfs2(k,f[k],1); 59 ans -- ; 60 num += ans; 61 int r = (num + 1) / 2; 62 int l = 0; 63 while(l < r){ 64 int mid = l + r>> 1; 65 int x = min(2 * mid,num); 66 int y = min(mid, ans); 67 if(x - dep[k] + 1>= y) r = mid; 68 else l = mid + 1; 69 } 70 printf("%d\n",l); 71 }