传送门
G 题
题目 :
、并且 p 是素数, 定义成
初始ai = 1, 有两种操作:
- 区间乘,将区间 (l,r)乘 x ,
- 区间查询
解法:
查询的是区间内 素数的最大幂数
对 2,3,5,7 分别维护一颗线段树,区间加、区间取 max 即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, q;
char s[10];
int a[10] = {2, 3, 5, 7};
int table[12][10];
void init(){
for(int i = 2; i <= 10; i++){
int tmp = i;
for(int j = 0; j < 4; j++){
int cnt = 0;
while(tmp%a[j] == 0){
cnt++;
tmp /= a[j];
}
table[i][j] = cnt;
}
}
}
int Max[N*4][4], lazy[N*4][4];
void push(int o){
for(int i = 0; i < 4; i++){
if(lazy[o][i]){
int tmp = lazy[o][i];
lazy[o<<1][i] += tmp;
Max[o<<1][i] += tmp;
lazy[o<<1|1][i] += tmp;
Max[o<<1|1][i] += tmp;
lazy[o][i] = 0;
}
}
}
void up(int o, int l, int r, int ql, int qr, int pos, int v){
if(ql <= l && qr >= r){
Max[o][pos] += v;
lazy[o][pos] += v;
return ;
}
push(o);
int mid = l+r >> 1;
if(ql <= mid) up(o<<1, l, mid, ql, qr, pos, v);
if(qr > mid) up(o<<1|1, mid+1, r, ql ,qr, pos, v);
for(int i = 0; i < 4; i++){
Max[o][i] = max(Max[o<<1][i], Max[o<<1|1][i]);
}
}
int qu(int o, int l, int r, int ql, int qr){
if(ql <= l && qr >= r){
int res = 0;
for(int i = 0; i < 4; i++){
res = max(res, Max[o][i]);
}
return res;
}
push(o);
int res = 0;
int mid = l+r>>1;
if(ql <= mid) res = max(res, qu(o<<1, l, mid, ql, qr));
if(qr > mid) res = max(res, qu(o<<1|1, mid+1, r, ql, qr));
for(int i = 0; i < 4; i++){
Max[o][i] = max(Max[o<<1][i], Max[o<<1|1][i]);
}
return res;
}
void pika(int l, int r, int w){
for(int i = 0; i < 4; i++){
if(table[w][i]){
up(1, 1, n, l, r, i, table[w][i]);
}
}
}
int main(){
scanf("%d%d", &n, &q);
init();
int l, r , w;
for(int i = 0; i < q; i++){
scanf("%s", s);
if(s[1] == 'U'){
scanf("%d%d%d", &l, &r, &w);
pika(l, r, w);
}
else{
scanf("%d%d", &l, &r);
int ans = qu(1, 1, n, l, r);
printf("ANSWER %d\n", ans);
}
}
return 0;
}
H题
spfa + slf 容错优化
SLF优化:将原队列改成双端队列,对要加入队列的点 v,如果 d[v] 小于队头元素d[q.front()],将其插入到队头,否则插入到队尾。
选择合适的容错值 sqrt(sum)/800 ~ sqrt(sum)/50
LLL优化:对每个要出队的队头元素 u,比较 dist[u] 和队列中点的 dist 的平均值,如果 dist[u] 更大,将其弹出放到队尾,然后取队首元素进行相同操作,直到队头元素的 dist 小于等于平均值。
这题SLF + LLL优化会T,SLF + 容错优化可以过。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e4;
const int M = 2e6;
const ll INF = 1e18;
int n, x, y, s;
struct Edge{
int to, next, w;
}e[M];
int head[N], tot = 0;
void addEdge(int u, int v, int w){
e[tot] = Edge{v, head[u], w};
head[u] = tot++;
}
ll d[N];
int vis[N];
ll val;
int q[M], l, r;
void spfa(){
for(int i = 1; i <= n; i++){
d[i] = INF;
}
d[s] = 0;
vis[s] = 1;
l = r = 1e6;
q[l] = s;
while(l <= r){
int u = q[l];
l++;
vis[u] = 0;
for(int i = head[u]; i != -1; i = e[i].next){
int v = e[i].to;
if(d[v] > d[u] + e[i].w){
d[v] = d[u] + e[i].w;
if(!vis[v]){
if(l > r || d[v] <= d[q[l]] + val){
q[--l] = v;
}
else{
q[++r] = v;
}
vis[v] = 1;
}
}
}
}
}
int main(){
scanf("%d%d%d%d", &n, &x, &y, &s);
memset(head, -1, sizeof(int)*(n+1));
int u, v, w;
for(int i = 0; i < x; i++) {
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
val += 2*w;
}
for(int i = 0; i < y; i++) {
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
val += w;
}
val = sqrt(val)/300;
spfa();
for(int i = 1; i <= n; i++){
if(d[i] == INF) printf("NO PATH\n");
else printf("%lld\n", d[i]);
}
return 0;
}
F 题
求
因为b >= a,所以 , 公式可以变为
当 时, 可以用分块算出答案, 当 时, = 1,公式可以变为
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
ll n;
ll qpow(ll a,int x){
ll res = 1;
while(x){
if(x&1) res = res * a % mod;
a = a * a % mod;
x /= 2;
}
return res;
}
ll get(ll x){
x %= mod;
return ((1+x)*x%mod*(n%mod+1)%mod*qpow(2,mod-2)%mod - x%mod*(x+1)%mod*(2*x+1)%mod*qpow(6,mod-2)%mod + mod)%mod;
}
int main(){
scanf("%lld", &n);
ll mx = sqrt(n)+1;
ll ans = 0;
for(int i = 2; i <= mx; i++){
ll k = i;
ll cnt = 1;
for(ll j = i; j <= n; j = k){
k *= i;
if(k <= n+1){
ans = (ans + (k-j)%mod*i%mod*cnt) % mod;
}
else{
ans = (ans + (n-j+1)%mod*i%mod*cnt) % mod;
}
cnt++;
}
}
ans = (ans + get(n) - get(mx) + mod)%mod;
printf("%lld\n", ans);
return 0;
}
K 题
首先处理好每个 aij 上、左、右对应的数字,然后就是一个悬线法模板题了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int n, m;
int a[N][N];
int p[4][N*N]; // 0上 1左 2右
int u[N][N], l[N][N], r[N][N];
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%d", &a[i][j]);
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
p[0][a[i][j]] = a[i-1][j];
p[1][a[i][j]] = a[i][j-1];
p[2][a[i][j]] = a[i][j+1];
}
}
for(int i = 1;i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%d", &a[i][j]);
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(p[0][a[i][j]] == a[i-1][j]){
u[i][j] = u[i-1][j] + 1;
}
else u[i][j] = 1;
if(p[1][a[i][j]] == a[i][j-1]){
l[i][j] = l[i][j-1] + 1;
}
else l[i][j] = 1;
}
for(int j = m; j >= 1; j--){
if(p[2][a[i][j]] == a[i][j+1]){
r[i][j] = r[i][j+1] + 1;
}
else r[i][j] = 1;
}
}
int mx = 0;
for(int i = 2; i <= n; i++){
for(int j = 1; j <= m; j++){
if(p[0][a[i][j]] == a[i-1][j]){
l[i][j] = min(l[i][j], l[i-1][j]);
r[i][j] = min(r[i][j], r[i-1][j]);
}
if(mx < (l[i][j] + r[i][j] - 1) * u[i][j]){
mx = (l[i][j] + r[i][j] - 1) * u[i][j];
}
}
}
printf("%d\n", mx);
return 0;
}
I 题
Java、Python练习题,注意特判0
Python ord() 函数获取字符ASCII码表对应的值。 chr()将值转化为对应字符
list = input().split()
x = int(list[0], 10)
y = int(list[1], 10)
zz = list[2]
z = 0
for i in zz:
z = z * x;
if i <= '9':
z += ord(i) - ord('0')
elif i <= 'Z':
z += ord(i) - ord('A') + 10
else :
z += ord(i) - ord('a') + 36
s = ''
while z != 0:
tmp = z % y
if tmp < 10:
s += chr(tmp + ord('0'))
elif tmp < 36:
s += chr(tmp - 10 + ord('A'))
else :
s += chr(tmp - 36 + ord('a'))
z //= y
ans = ''
for i in range(len(s)-1, -1, -1):
ans += s[i]
if len(ans) == 0:
ans += '0'
print(ans)
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static long getValue(char c){
if(c <= '9' && c >= '0'){
return c - '0';
}
else if(c <= 'z' && c >= 'a'){
return c - 'a' + 36;
}
else{
return c - 'A' + 10;
}
}
static char getChar(String s){
int tmp = 0;
for(int i = 0; i < s.length(); i++){
tmp = tmp * 10 + s.charAt(i) - '0';
}
if(tmp < 10){
return (char)('0' + tmp);
}
else if(tmp < 36){
return (char)('A' + tmp - 10);
}
else{
return (char)('a' + tmp - 36);
}
}
public static void main(String[] args) {
BigInteger x;
BigInteger y;
String s;
Scanner sc = new Scanner(System.in);
x = sc.nextBigInteger();
y = sc.nextBigInteger();
s = sc.nextLine();
BigInteger a = new BigInteger("0");
BigInteger zero = new BigInteger("0");
BigInteger tmp;
for(int i = 1; i < s.length(); i++){
tmp = BigInteger.valueOf(getValue(s.charAt(i)));
a = a.multiply(x).add(tmp);
}
String ans = "";
while(!a.equals(zero)) {
tmp = a.mod(y);
char c = getChar(tmp.toString());
ans += c;
a = a.divide(y);
}
for(int i = ans.length()-1; i >= 0; i--){
System.out.print(ans.charAt(i));
}
if(ans.length() == 0) System.out.print("0");
System.out.println("");
}
}