已ac 8/12,赛时7题,赛后1题。
要么 n 要么 n-1.
FastIO 已省略
def solve():
n,s = MI()
a = LI()
print1(n if sum(a) == s else n-1)
# for _ in range(I()):
solve()
给你一个长度不超过 1 0 14 10^{14} 1014 的11进制数,判断是不是5的倍数,由于 1 1 i m o d 10 = 1 11^i \mod 10 = 1 11imod10=1,所以所有位累加即可。
mod = 5
dic = {str(i):i for i in range(10)}
dic['A'] = 10
def solve():
n = I()
ans = 0
for i in range(n):
x,y = MS()
ans += int(x) * dic[y]
ans %= 5
print('Yes' if ans % 5 == 0 else 'No')
for _ in range(I()):
solve()
# print(set([pow(11,i,10) for i in range(100000)]))
se = set()
for c in "psm":
se.add('1'+c)
se.add('9'+c)
for i in range(1,8):
se.add(str(i) + 'z')
def solve():
s = S()
dic = {}
for i in range(0,28,2):
ts = s[i:i+2]
dic[ts] = dic.get(ts,0)+1
flag = 1
for v in dic.values():
if v != 2:
flag = 0
break
if flag:
print1("7 Pairs")
return
if se == set(dic.keys()): print1("Thirteen Orphans")
else: print1("Otherwise")
for _ in range(I()):
solve()
显然有m-1种分叉情况,所以 a n s = 2 m − 1 ans = 2^{m-1} ans=2m−1 % m o d mod mod .
mod = 998244353
def solve():
m = I()
print1(pow(2, m-1, mod))
solve()
考虑把卷积核 K K K 加权到输入矩阵 I I I 的过程反过来看,判断卷积核 K K K 的每一个元素会扫到哪些 I I I (即局部链接了哪些ceil). 用个二维前缀和维护一下即可。
def solve():
n,m,k,l = MI()
ls = [[0]*(m+1)]
for i in range(n):
ls.append([0]+LI())
for i in range(1,n+1):
for j in range(1,m+1):
ls[i][j] = ls[i][j] + ls[i-1][j] + ls[i][j-1] - ls[i-1][j-1]
ans = 0
for i in range(1,k+1):
for j in range(1,l+1):
tmp = ls[n-k+i][m-l+j] - ls[n-k+i][j-1] - ls[i-1][m-l+j] + ls[i-1][j-1]
ans += abs(tmp)
print1(ans)
solve()
假设 k k k 个出口开放区间最多组成 l e n ( s e q ) len(seq) len(seq) 个不同情况的时间区间(出口不一样),考虑每个区间跑一次 d i j k s t r a dijkstra dijkstra 即可, k ≤ 15 k\le15 k≤15。注:py会TLE。
#include
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+5;
int n,m,tot,k,t;
int ver[N+N], head[N], edge[N+N], nxt[N+N], a[N];
ll ans[N], inf = 1e15;
ll dist[N];
int p[20], l[20], r[20], node[20];
bool vis[N];
int ls[N];
vector<pii> seq;
void solve()
{
auto add = [&](int x,int y,int z){
ver[++tot]=y,edge[tot]=z;
nxt[tot]=head[x],head[x]=tot;
};
auto dijkstra = [&](int node[]){
priority_queue<pair<int, int> > q;
for(int i = 1; i <= k; i++){
if (node[i]){
dist[p[i]] = 0;
q.push({-0,p[i]});
}
}
while(!q.empty()){
pii tmp = q.top();q.pop();
int x = tmp.second;
if(vis[x]) continue;
vis[x] = 1;
for(int i=head[x]; i; i=nxt[i]){
int y=ver[i];
int w=edge[i];
if (dist[y] > dist[x] + w){
dist[y] = dist[x] + w;
q.push({-dist[y], y});
}
}
}
};
cin>>n>>m>>k>>t;
for(int i=1; i <= n; i++) cin>>a[i];
for(int i=1; i <= k; i++) {
cin>>p[i]>>l[i]>>r[i];
ls[l[i]] += k;
ls[r[i] + 1] -= k;
}
for(int i=1;i<=m;++i){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
for(int i = 1; i <= t; i++) ls[i] += ls[i-1];
int st = 1, pre =ls[1];
ls[t+1] = -1;
for(int i = 1; i <= t+1; i++){
if (ls[i] != pre){
seq.push_back({st, i-1});
st = i; pre = ls[i];
}
}
for(int i = 1; i <= t; i++) ans[i] = 1e18;
for(int i = 0; i < seq.size(); i++){
for(int j = 1; j <= n; j++) {dist[j] = inf;vis[j] = 0;}
for(int j = 1; j <= k; j++) node[j] = 0;
for(int j = 1; j <= k; j++)
if (l[j] <= seq[i].first && r[j] >= seq[i].second) node[j] = 1;
dijkstra(node);
ll cnt = 0;
bool fl = false;
for(int j = 1; j <= n; j++){
if (dist[j] == inf) {fl = 1;break;}
cnt += dist[j] * a[j];
}
if (fl) continue;
for(int j = seq[i].first; j <= seq[i].second; j++)
ans[j] = min(ans[j], cnt);
}
for(int i = 1; i <= t; i++)
if (ans[i] < 1e18) cout<<ans[i]<<'\n';
else cout<<-1<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
考虑操作的本质是什么,对于两个数的所有质因子(并集),假设其中一对分别有 p c , p d p^c,p^d pc,pd ,那么一个变为 p max ( c , d ) p^{\max(c,d)} pmax(c,d) 一个变为 p min ( c , d ) p^{\min(c,d)} pmin(c,d)。
那我们可以使用筛法筛出每个数的最小质因子进行分解,把能转移的都转移到同一个最大的数上即可。
#include
using namespace std;
typedef long long ll;
const int N=1e6;
const ll mod=998244353;
int n;
int mx[N+1];
int cnt[N+1][20];
vector<int> minp, primes;
void sieve(int n) {
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
void solve()
{
cin >> n;
vector<int> v(n);
for(int i = 0; i < n; i++)
cin >> v[i];
vector<int> stk;
for(int i = 0; i < n; i++){
while(v[i] > 1){
int p = minp[v[i]];
int t = 0;
while(minp[v[i]] == p){ // 求质因子的次幂
v[i] /= p;
t++; // 将所有涉及到的质因数入栈
}
if(mx[p] == 0)
stk.push_back(p); // 质因数中第一次遇到 p 只入栈一次
mx[p] = max(mx[p], t);
cnt[p][t]++;
}
}
vector<ll> a(n, 1); // 所有操作后的 v
for (auto p : stk){ // 枚举涉及到的所有质因数
int j = 0;
for (int i = mx[p]; i; i--){ // 统计该质因数为i次幂在v中出现的次数
j += cnt[p][i];
}
ll pw = 1;
for (int i = 1; i <= mx[p]; i++){
pw = (1ll * pw * p) % mod;
while (cnt[p][i]){
cnt[p][i]--;
a[j] = (a[--j] * pw) % mod;
}
}
mx[p] = 0;
}
ll ans = 0;
for(auto x : a)
ans = (ans + x) % mod;
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
sieve(N);
int T = 1;
cin >> T;
while(T--)
solve();
return 0;
}