\(A. Girls Band Party\)
\(B. So Easy\)
给\(n\)行\(n\)列分别加上一个\(\ge 0\)的数,已知其他位置的数,求\(x\)行\(y\)列处的数是多少
每行每列全都减去当前行或列最小的那个数,第\(x\)行减去的值和第\(y\)列减去的值的和就是答案
相当于原来操作的逆操作
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
int n,A[MAXN][MAXN];
void solve(){
cin >> n;
int x,y,ret=0;
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){
cin >> A[i][j];
if(A[i][j]==-1) x = i, y = j;
}
for(int i = 1; i <= n; i++){
int minn = 1e7;
for(int j = 1; j <= n; j++) if(A[i][j]>=0) minn = min(minn,A[i][j]);
for(int j = 1; j <= n; j++) A[i][j] -= minn;
if(i==x) ret+=minn;
}
for(int i = 1; i <= n; i++){
int minn = 1e7;
for(int j = 1; j <= n; j++) if(A[j][i]>=0) minn = min(minn,A[j][i]);
for(int j = 1; j <= n; j++) A[j][i] -= minn;
if(i==y) ret+=minn;
}
cout << ret << endl;
}
int main(){
____();
solve();
return 0;
}
\(C. Image Processing\)
\(D. Easy Problem\)
\[计算\sum (a_1\cdot a_2 \cdot a_3 \cdots a_n)^k\ 其中gcd(a_1,a_2,a_3,\cdots,a_n)=d且a_i\le m \]
转化一下,就是计算:
\[(d^k)^n\sum (b_1\cdot b_2 \cdot b_3 \cdots b_n)^k\ 其中gcd(b_1,b_2,b_3,\cdots,b_n)=1且b_i\le \lfloor \frac{m}{d}\rfloor \]
考虑如何计算\(\sum (x_1\cdot x_2\cdot x_3\cdots x_n)^k\),其中\(1\le x_i\le m\)
\(\sum (x_1\cdot x_2\cdot x_3\cdots x_n)^k = \sum (x_1^k\cdot x_2^k\cdot x_3^k\cdots x_n^k) = (\sum_{i=1}^{m}i^k)^n\)
然后我们需要去掉\(gcd(b_1,b_2,b_3,\cdots,b_n)\ne 1\)的情况,这是个和约数相关的容斥原理,容斥系数就是莫比乌斯函数
所以最后可以得到:
\[resault = (d^k)^n\cdot \sum_{i=1}^{\lfloor \frac{m}{d}\rfloor} \mu (i)((\sum_{j=1}^{\lfloor \frac{m}{id}\rfloor}j^k)(i^k))^n \]
内部可以用前缀和预处理加上快速幂复杂度大概是\(O(Tm\log(MOD))\)
注意这里的模数\(59964251\)不是质数,大数幂的时候需要用扩展欧拉定理
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
using LL = int_fast64_t;
const LL MOD = 59964251;
const LL phi = 59870352;
char n[MAXN];
LL m, d, k, pre[MAXN];
int mu[MAXN],npm[MAXN];
vector<int> prime;
LL qpow(LL a, LL b){
LL ret = 1;
while(b){
if(b&1) ret = ret * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ret;
}
void preprocess(){
mu[1] = 1;
for(int i = 2; i < MAXN; i++){
if(!npm[i]) prime.emplace_back(i), mu[i] = -1;
for(int j = 0; j < (int)prime.size(); j++){
if(i*prime[j]>=MAXN) break;
npm[i*prime[j]] = true;
mu[i*prime[j]] = -mu[i];
if(i%prime[j]==0){
mu[i*prime[j]] = 0;
break;
}
}
}
}
void solve(){
cin >> n >> m >> d >> k;
LL pw = 0;
for(int i = 0, len = strlen(n); i < len; i++) pw = (pw * 10 + n[i]-'0') % phi; //扩展欧拉定理
pw += phi;
k = k % phi + phi;
for(int i = 1; i <= m; i++) pre[i] = (pre[i-1] + qpow(i,k)) % MOD;
LL ret = 0;
for(int i = 1; i <= m / d; i++) ret = (ret + mu[i] * qpow((pre[m/(i*d)]*qpow(i,k))%MOD,pw)) % MOD;
ret = ret * qpow(qpow(d,k),pw) % MOD;
if(ret<0) ret += MOD;
cout << ret << endl;
}
int main(){
____();
int T;
preprocess();
for(cin >> T; T; T--) solve();
return 0;
}
\(E. XOR Tree\)
\(F. Function!\)
\[计算 \sum_{a=2}^{n}(a\sum_{b=a}^{n}\lfloor\log_{a}b\rfloor),n\le 10^{12} \]
发现\(a>\lfloor \sqrt{n}\rfloor\)时,后面的和式变成了\(a\sum_{b=a}^{n}1=a\cdot(n-a+1)\)
所以而在\(\sqrt{n}\)之前的可以枚举\(\lfloor\log_ab\rfloor\)来计算,式子变成:
\[\sum_{a=2}^{\lfloor \sqrt{n}\rfloor}(a\sum_{b=a}^{n} \lfloor\log_{a}b\rfloor)+\sum_{a=\lfloor\sqrt{n}\rfloor +1}^{n}(a\cdot (n-a+1)) \]
复杂度\(O(\sqrt{n}\log{n})\)
计算\(\sum_{x=1}^{n}x^2\)的公式是\(\frac{n\cdot (n+1)\cdot (2\cdot n+1)}{6}\)
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const LL MOD = 998244353;
LL qpow(LL a, LL b){
LL ret = 1;
while(b){
if(b&1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret;
}
LL inv(LL x){ return qpow(x,MOD-2); }
LL n;
int main(){
____();
cin >> n;
int sqt = (int)sqrt(n);
LL ret = 0;
for(int a = 2; a <= sqt; a++){
LL pre = a;
int add = 0;
while(true){
add++;
LL now = min(n,pre*a-1);
ret = (ret + (now-pre+1) * add * a) % MOD;
if(now==n) break;
pre *= a;
}
}
LL x = sqt + 1, m = n % MOD;
ret = (ret + (m+1) % MOD * (x+m) % MOD * (m-x+1) % MOD * inv(2)) % MOD;
ret = (ret - m * (m+1) % MOD * (2*m+1) % MOD * inv(6) % MOD + (x-1) * x % MOD * (2*x-1) % MOD * inv(6)) % MOD;
if(ret < 0) ret += MOD;
cout << ret << endl;
return 0;
}
\(G. Pot!!\)
\(10\)以内的质数只有\(2,3,5,7\),线段树维护区间内四个质数出现次数的最大值即可
更新的时候区间内把\(x\)分解质因子之后区间更新
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
struct SegmentTree{
int maxx[MAXN<<2][4],lazy[MAXN<<2][4];
int l[MAXN<<2],r[MAXN<<2];
#define ls(rt) rt << 1
#define rs(rrt) rt << 1 | 1
void pushup(int rt){
for(int i = 0; i < 4; i++) maxx[rt][i] = max(maxx[ls(rt)][i],maxx[rs(rt)][i]);
}
void pushdown(int rt){
for(int i = 0; i < 4; i++){
if(!lazy[rt][i]) continue;
maxx[ls(rt)][i] += lazy[rt][i]; lazy[ls(rt)][i] += lazy[rt][i];
maxx[rs(rt)][i] += lazy[rt][i]; lazy[rs(rt)][i] += lazy[rt][i];
lazy[rt][i] = 0;
}
}
void build(int L, int R, int rt = 1){
l[rt] = L, r[rt] = R;
if(L+1==R) return;
int mid = (L+R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
}
void update(int L, int R, int tg, int rt = 1){
if(L>=r[rt] or l[rt]>=R) return;
if(L<=l[rt] and r[rt]<=R){
maxx[rt][tg]++;
lazy[rt][tg]++;
return;
}
pushdown(rt);
update(L,R,tg,ls(rt)); update(L,R,tg,rs(rt));
pushup(rt);
}
int query(int L, int R, int tg, int rt = 1){
if(L>=r[rt] or l[rt]>=R) return 0;
if(L<=l[rt] and r[rt]<=R) return maxx[rt][tg];
pushdown(rt);
return max(query(L,R,tg,ls(rt)),query(L,R,tg,rs(rt)));
}
}ST;
int n,m;
int main(){
scanf("%d %d",&n,&m);
ST.build(1,n+1);
char op[20];
for(int i = 1; i <= m; i++){
scanf("%s",op);
if(op[1]=='A'){
int l, r, ret = 0; scanf("%d %d",&l,&r);
r++;
for(int k = 0; k < 4; k++) ret = max(ret,ST.query(l,r,k));
printf("ANSWER %d\n",ret);
}
else{
int l, r, x; scanf("%d %d %d",&l,&r,&x);
r++;
while(x-1 and x%2==0) x/=2, ST.update(l,r,0);
while(x-1 and x%3==0) x/=3, ST.update(l,r,1);
while(x-1 and x%5==0) x/=5, ST.update(l,r,2);
while(x-1 and x%7==0) x/=7, ST.update(l,r,3);
}
}
return 0;
}
\(H. Delivery Route\)
BZOJ2200
Dijkstra不能跑负权图 所以可以先缩点,缩点完之后就是一个DAG,其中可以对每个连通块跑Dijkstra
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e5+7;
const int INF = 0x3f3f3f3f;
int n,x,y,s,sccid[MAXN],sid,deg[MAXN],dist[MAXN];
bool vis[MAXN];
vector<int> scc[MAXN];
int Stk[MAXN], tp;
bool instk[MAXN];
int top(){ return Stk[tp]; }
void pop(){ instk[Stk[tp--]] = false; }
void push(int x){ instk[Stk[++tp]=x] = true; }
bool check(int x){ return instk[x]; }
struct Graph{
int to[MAXN<<2],nxt[MAXN<<2],w[MAXN<<2],head[MAXN],tot;
Graph(){}
void ADDEDGE(int u, int v, int x){
tot++;
to[tot] = v; nxt[tot] = head[u]; w[tot] = x;
head[u] = tot;
}
}G;
void gao(int u, int id){
sccid[u] = id;
scc[id].push_back(u);
for(int i = G.head[u]; i; i = G.nxt[i]) if(!sccid[G.to[i]]) gao(G.to[i],id);
}
void dfs(int u){
vis[u] = true;
for(int i = G.head[u]; i; i = G.nxt[i]) if(!vis[G.to[i]]) dfs(G.to[i]);
}
void rebuild(){
for(int u = 1; u <= n; u++){
if(!vis[u]) continue;
for(int i = G.head[u]; i; i = G.nxt[i]){
int v = G.to[i];
if(!vis[v] or sccid[u]==sccid[v]) continue;
deg[sccid[v]]++;
}
}
}
queue<int> que;
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
void Dijkstra(int ss){
for(int v : scc[ss]) if(dist[v]!=INF) pq.push(make_pair(dist[v],v));
while(!pq.empty()){
auto p = pq.top();
pq.pop();
int u = p.second;
if(dist[u]!=p.first) continue;
for(int i = G.head[u]; i; i = G.nxt[i]){
int v = G.to[i], w = G.w[i];
if(!vis[v]) continue;
if(sccid[v]!=sccid[u]) if(!--deg[sccid[v]]) que.push(sccid[v]);
if(dist[v]>dist[u]+w){
dist[v] = dist[u] + w;
if(sccid[v]==sccid[u]) pq.push(make_pair(dist[v],v));
}
}
}
}
void solve(){
memset(dist,0x3f,sizeof(dist));
dist[s] = 0;
que.push(sccid[s]);
while(!que.empty()){
int ss = que.front();
que.pop();
Dijkstra(ss);
}
for(int i = 1; i <= n; i++){
if(dist[i]==INF) puts("NO PATH");
else printf("%d\n",dist[i]);
}
}
int main(){
scanf("%d %d %d %d",&n,&x,&y,&s);
for(int i = 1; i <= x; i++){
int u, v, w; scanf("%d %d %d",&u,&v,&w);
G.ADDEDGE(u,v,w); G.ADDEDGE(v,u,w);
}
for(int i = 1; i <= n; i++) if(!sccid[i]) gao(i,++sid);
for(int i = 1; i <= y; i++){
int u, v, w; scanf("%d %d %d",&u,&v,&w);
G.ADDEDGE(u,v,w);
}
dfs(s);
rebuild();
solve();
return 0;
}
\(I. Base62\)
大数的进制转换,用不想写c++,那就用直接Java
import java.io.*;
import java.util.*;
import java.math.*;
public class Main{
private static Scanner cin = new Scanner(new BufferedInputStream(System.in));
private static PrintWriter cout = new PrintWriter(System.out,true);
private static InputStream inputstream = System.in;
public static void main(String[] args){
Task solver = new Task();
int TaskCase = 1;
while(TaskCase--!=0){
solver.solve();cout.flush();
}
}
private static class Task{
HashMap<Character,Integer> map1 = new HashMap<>();
HashMap<Integer,Character> map2 = new HashMap<>();
public void solve(){
for(int i = 0; i <= 9; i++){
map1.put((char)(i+(int)('0')),i);
map2.put(i,(char)(i+(int)('0')));
}
for(int i = (int)('A'); i <= (int)('Z'); i++){
map1.put((char)(i),i-(int)('A')+10);
map2.put(i-(int)('A')+10,(char)(i));
}
for(int i = (int)('a'); i <= (int)('z'); i++){
map1.put((char)(i),i-(int)('a')+36);
map2.put(i-(int)('a')+36,(char)(i));
}
int base1 = cin.nextInt(), base2 = cin.nextInt();
String str1 = cin.next();
BigInteger bs1 = BigInteger.valueOf(base1);
BigInteger bs2 = BigInteger.valueOf(base2);
BigInteger base10 = BigInteger.ZERO;
for(int i = 0; i < str1.length(); i++){
base10 = base10.multiply(bs1).add(BigInteger.valueOf(map1.get(str1.charAt(i))));
}
ArrayList<Integer> arr = new ArrayList<>();
if(base10.equals(BigInteger.ZERO)) arr.add(0);
while(!(base10.equals(BigInteger.ZERO))){
arr.add(base10.mod(bs2).intValue());
base10 = base10.divide(bs2);
}
for(int i = arr.size() - 1; i >= 0; i--) cout.write(map2.get(arr.get(i)));
}
}
}
\(J. Toad’s Travel\)
\(K. Largest Common Submatrix\)
由于\(AB\)两个矩阵中每个数都只出现一次,所以我们新建一个矩阵\(C\),矩阵里存放\(A\)中每个位置\(x,y\)对应的数在B矩阵中的位置和在\(A\)矩 阵中的位置的差值,现在问题转化为找一个最大的子矩阵\(Mat\)使得这个矩阵中的所有值相同,单调栈做就好了
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
int n,m,A[MAXN][MAXN],B[MAXN][MAXN],f[MAXN][MAXN],l[MAXN],r[MAXN];
pair<int,int> pos[MAXN*MAXN],mat[MAXN][MAXN];
pair<int,int> operator - (const pair<int,int> &lhs, const pair<int,int> &rhs){
return make_pair(lhs.first-rhs.first,lhs.second-rhs.second);
}
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++) scanf("%d",&B[i][j]), pos[B[i][j]] = make_pair(i,j);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) mat[i][j] = make_pair(i,j) - pos[A[i][j]];
for(int i = 1; i <= n; i++) for(int j = m; j >= 1; j--){
f[i][j] = 1; if(j==m) continue;
if(mat[i][j]==mat[i][j+1]) f[i][j] += f[i][j+1];
}
int ret = 0;
for(int i = 1; i <= m; i++){
stack<int> stk;
memset(l,0,sizeof(l)); memset(r,0,sizeof(r));
for(int j = 1; j <= n; j++){
if(!stk.empty()){
if(mat[j][i]!=mat[j-1][i]){
while(!stk.empty()){
r[stk.top()] = j - 1;
stk.pop();
}
}
}
while(!stk.empty() and f[j][i]<f[stk.top()][i]){
l[j] = l[stk.top()];
r[stk.top()] = j - 1;
stk.pop();
}
if(!l[j]) l[j] = j;
stk.push(j);
}
while(!stk.empty()){
r[stk.top()] = n;
stk.pop();
}
for(int j = 1; j <= n; j++) ret = max(ret,(r[j]-l[j]+1)*f[j][i]);
}
cout << ret << endl;
return 0;
}
\(L. Xian Xiang\)
\(M. Crazy Cake\)
\(N. Fibonacci Sequence\)
输出\(1,1,2,3,5\)
python写一行就完了
print(1,1,2,3,5)