题目链接
You are currently playing a game called “Garupa”. In an event of the game, you are trying to get more event points. You have nn cards, each with its own name, color, and power. When you play the game, you can put five cards of different names into your deck. The base point of this event is the sum of the power of the cards in your deck. On top of that, the event publishes a color and five names as bonus attributes, which means that each time you have a card with a bonus color in the deck, you end up with a 20 % 20\% 20% increase in event point. And each time you have a card with a bonus name in the deck, you will eventually get 10 % 10\% 10% of the event point (bonus values are calculated by addition, and we round down when calculating the final event point). Please find the maximum event point you will eventually get.
The first line is an integer T ( 1 ≤ T ≤ 50 ) T~(1 \leq T \leq 50) T (1≤T≤50), which is the number of test cases.
For each set of input data, input a positive integer n ( 5 ≤ n ≤ 100000 ) n~(5 \leq n \leq 100000) n (5≤n≤100000) in the first line to indicate the number of cards you have.
The next nn lines, the ii-th line input two strings n a m e i name_i namei, c o l o r i color_i colori and a positive integer p o w e r i ( 1 ≤ p o w e r i ≤ 50000 ) power_i~(1 \leq power_i \leq 50000) poweri (1≤poweri≤50000) separated by spaces, indicating the name, color, and power of the i i i-th card. The input data ensures that there are at least five cards with different names.
The next line input five strings representing the five bonus names. The input data guarantees that the bonus names are different.
The last line input a string representing a bonus color.
The input data ensures that all strings consist of only uppercase and lowercase letters and the max length of them is 10 10 10, and the sum of n n n in all sets of input data does not exceed 1500000 1500000 1500000.
每个卡片有一个名字、一个颜色和一个权值。有5种名字的卡片能带来 10 % 10\% 10%的加成,有1种颜色的卡片能带来 20 % 20\% 20%的加成。
让你从n张卡片里选择名字不同的5张卡片。总加成初始为1,若选择的卡片名字出现在5种加成名字中,则总加成 + 10 % +10\% +10%,若选择的卡片颜色与加成颜色一样,则总加成 + 20 % +20\% +20%;基础得分为5张卡片的权值之和, 总 得 分 = 基 础 得 分 ∗ 总 加 成 之 和 总得分=基础得分*总加成之和 总得分=基础得分∗总加成之和,求最大总得分。
For each set of data, output only one line of a positive integer, indicating the maximum number of bonus points that you will eventually get.
1
6
Saaya Power 45000
Kokoro Happy 45000
Kasumi Cool 45000
Rimi Power 45000
Aya Pure 45000
Aya Power 2000
Saaya Tae Kasumi Rimi Arisa
Power
382500
所有的牌都可以分为4类
1:名字没有加成,颜色没有加成
2:名字有加成,颜色没有加成
3:名字没有加成,颜色有加成
4:名字有加成,颜色有加成
把类别相同的都放在同一个数组中,把每个数组都按照power从大到小排序。对每个数组去重,每个名字只保留power最高的。
设最后的四个数组为V[1],V[2],V[3],V[4],然后爆搜即可:
每次从V[0],V[1],V[2],V[3]中选取一张牌,优先选power最高的,如果名字重复就跳过。
详细过程见代码与注释。
#include
using namespace std;
const int MAXN = 1e5 + 50;
int T, n;
double ans;
//totn为不同的name个数,totc为不同的color个数
int totn, totc;
string ss;
//mpn, mpc分别用来把name、color用数字进行映射代替
map<string, int> mpn, mpc;
int rwdn[6], tr, rwdc;//记录加成名字的标号、加成颜色的标号
struct Info
{
int nam, col, pwr;
}a[MAXN], v[5][MAXN];
int tot[5];
/*
1: none;
2: name;
3: color;
4: both;
*/
bool cmp1(Info a, Info b)
{
return a.nam == b.nam ? a.pwr > b.pwr : a.nam < b.nam;
}
bool cmp2(Info a, Info b)
{
return a.pwr > b.pwr;
}
set<int> usd;
set<int>::iterator it;
void dfs(int dep, int cntn, int cntc, int pwr, int i1, int i2, int i3, int i4)
{
//参数意义:搜索深度,name加成个数,color加成个数,当前总power,四个数组选择到了哪里
if(dep == 6)
{
ans = max(ans, (1.0 + 0.1 * cntn + 0.2 * cntc) * pwr);
return;
}
if(i1 <= tot[1] && usd.find(v[1][i1].nam) == usd.end())
{
usd.insert(v[1][i1].nam);
dfs(dep+1, cntn, cntc, pwr+v[1][i1].pwr, i1+1, i2, i3, i4);
usd.erase(v[1][i1].nam);
}
else if(i1+1 <= tot[1]) dfs(dep, cntn, cntc, pwr, i1+1, i2, i3, i4);
if(i2 <= tot[2] && usd.find(v[2][i2].nam) == usd.end())
{
usd.insert(v[2][i2].nam);
dfs(dep+1, cntn+1, cntc, pwr+v[2][i2].pwr, i1, i2+1, i3, i4);
usd.erase(v[2][i2].nam);
}
else if(i2+1 <= tot[2]) dfs(dep, cntn, cntc, pwr, i1, i2+1, i3, i4);
if(i3 <= tot[3] && usd.find(v[3][i3].nam) == usd.end())
{
usd.insert(v[3][i3].nam);
dfs(dep+1, cntn, cntc+1, pwr+v[3][i3].pwr, i1, i2, i3+1, i4);
usd.erase(v[3][i3].nam);
}
else if(i3+1 <= tot[3]) dfs(dep, cntn, cntc, pwr, i1, i2, i3+1, i4);
if(i4 <= tot[4] && usd.find(v[4][i4].nam) == usd.end())
{
usd.insert(v[4][i4].nam);
dfs(dep+1, cntn+1, cntc+1, pwr+v[4][i4].pwr, i1, i2, i3, i4+1);
usd.erase(v[4][i4].nam);
}
else if(i4+1 <= tot[4]) dfs(dep, cntn, cntc, pwr, i1, i2, i3, i4+1);
}
void clear()
{
totn = totc = tr = 0;
memset(tot, 0, sizeof(tot));
ans = 0;
mpn.clear(); mpc.clear();
}
int main()
{
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
//对名字、颜色进行映射标号
cin >> ss;
if(mpn[ss]) a[i].nam = mpn[ss];
else a[i].nam = mpn[ss] = ++totn;
cin >> ss;
if(mpc[ss]) a[i].col = mpc[ss];
else a[i].col = mpc[ss] = ++totc;
scanf("%d", &a[i].pwr);
}
for(int i = 1; i <= 5; i++)
{
//对加成name进行标号(未出现过则无意义,不标号)
cin >> ss;
if(mpn[ss]) rwdn[++tr] = mpn[ss];
}
cin >> ss;
//对加成color标号,若不存在则标-1
rwdc = mpc[ss] ? mpc[ss] : -1;
for(int i = 1; i <= n; i++)
{
//将每张卡片分类(标准见上)
int flag = 1;
for(int j = 1; j <= tr; j++)
{
if(a[i].nam == rwdn[j])
{
if(a[i].col == rwdc) v[4][++tot[4]] = a[i];
else v[2][++tot[2]] = a[i];
flag = 0; break;
}
}
if(flag)
{
if(a[i].col == rwdc) v[3][++tot[3]] = a[i];
else v[1][++tot[1]] = a[i];
}
}
for(int i = 1; i <= 4; i++)
{
int sz = tot[i];
tot[i] = 0;
//按照name优先、power次优的顺序排序,这样相同的名字都排在了一起,第一个为power最大的
sort(v[i]+1, v[i]+1+sz, cmp1);
//去重:同类型且同名的,power较小的肯定不选
for(int j = 1; j <= sz; j++) if(v[i][j].nam != v[i][j-1].nam) v[i][++tot[i]] = v[i][j];
//按照power从小到大重新排序
sort(v[i]+1, v[i]+1+tot[i], cmp2);
}
dfs(1, 0, 0, 0, 1, 1, 1, 1);
int opt = int(ans);
printf("%d\n", opt);
clear();
}
return 0;
}
题目链接
Mr. G invents a new game whose rules are given as follows.
Firstly, he has a n × n n \times n n×n matrix, all elements of which are 0 0 0 initially. Then, he follows up with some operations: in each time he chooses a row or a column, and adds an arbitrary positive integer to all the elements in the selected row or column. When all operations have been finished, he hides an element in the matrix and the element is modified to − 1 -1 −1.
Now given the final matrix, you are asked to find out what the hidden element should be before the very last hiding operation.
一个初始为 n × n n\times n n×n 的矩阵初始全为 0 0 0,经过数次操作(每次操作可以将一行或者一列全都加上一个正整数)后得到了一个最终矩阵。现在把这个矩阵的一个元素改成 − 1 -1 −1后给你,求这个元素原先是多少。
The first line contains a single integer n ( 2 ≤ n ≤ 1000 ) n~(2 \leq n \leq 1000) n (2≤n≤1000).
Next nn lines represent the matrix after the operations. Each element in the matrix satisfies − 1 ≤ a i , j ≤ 1000000 -1 \leq a_{i,j} \leq 1000000 −1≤ai,j≤1000000, and exactly one element is − 1 -1 −1.
Output a single integer, the hidden element.
3
1 2 1
0 -1 0
0 1 0
1
设最终矩阵为A。先将A每行都减去其最小值,得到B;再将B每列都减去其最小值,得到C。C应为零矩阵。
#include
using namespace std;
const int MAXN = 1e3 + 10;
const int INF = 1e9;
int n, a[MAXN][MAXN];
int x, y;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%d", &a[i][j]);
if(a[i][j] == -1) {x = i; y = j;}
}
}
a[x][y] = INF;
for(int i = 1; i <= n; i++)
{
int minn = 1e9;
for(int j = 1; j <= n; j++) minn = min(minn, a[i][j]);
for(int j = 1; j <= n; j++) a[i][j] -= minn;
}
for(int j = 1; j <= n; j++)
{
int minn = 1e9;
for(int i = 1; i <= n; i++) minn = min(minn, a[i][j]);
for(int i = 1; i <= n; i++) a[i][j] -= minn;
}
printf("%d\n", INF - a[x][y]);
return 0;
}
题目链接
A sequence ( a 1 , a 2 , . . . , a n ) (a_{1},a_{2},...,a_{n}) (a1,a2,...,an) is ( n , m , d ) (n,m,d) (n,m,d)-good if 1 ≤ a i ≤ m ( 1 ≤ i ≤ n ) 1 \leq a_{i} \leq m~(1 \le i \le n) 1≤ai≤m (1≤i≤n) and gcd ( a 1 , a 2 , ⋯ , a n ) = d \gcd(a_{1},a_{2},\cdots,a_{n})=d gcd(a1,a2,⋯,an)=d.
Given four integers n , m , d n, m, d n,m,d and k k k, you are asked to calculate the sum of f ( q , k ) f(q, k) f(q,k) for each (n, m, d)-good sequence q q q, where f ( ( a 1 , a 2 , . . . a n ) , k ) = ( a 1 a 2 ⋯ a n ) k f((a_{1},a_{2},...a_{n}),k) = (a_{1}a_{2} \cdots a_{n})^{k} f((a1,a2,...an),k)=(a1a2⋯an)k for the sequence q = ( a 1 , a 2 , . . . a n ) q = (a_{1},a_{2},...a_{n}) q=(a1,a2,...an).
Since the answer could be very large, you only need to output the answer modulo 59964251 59964251 59964251.
The first line is an integer T ( 1 ≤ T ≤ 20 ) T~(1 \leq T \leq 20) T (1≤T≤20), which is the number of test cases.
For each test case, the first line contains four integers n ( 1 ≤ n ≤ 1 0 100000 ) , m ( 1 ≤ m ≤ 100000 ) , d ( 1 ≤ d ≤ 100000 ) , k ( 1 ≤ k ≤ 1 0 9 ) n~(1 \leq n \leq 10^{100000}), m~(1 \leq m \leq 100000), d~(1 \leq d \leq 100000), k~(1 \leq k \leq 10^9) n (1≤n≤10100000),m (1≤m≤100000),d (1≤d≤100000),k (1≤k≤109), which are described in the problem description.
For each test case, output a line containing a single integer.
1
3 3 3 1
27
由于 gcd ( a 1 , a 2 , ⋯ , a n ) = d \gcd(a_{1},a_{2},\cdots,a_{n})=d gcd(a1,a2,⋯,an)=d,因此我们可以将每个数提出一个 d d d,在式子外面乘上一个 ( d k ) n (d^k)^n (dk)n。
剩下可选取的数:
[ ⌊ m d ⌋ ⌊ m d ⌋ . . . ⌊ m d ⌋ ⌊ m d ⌋ . . . . . . . . . . . . . . . 3 3 . . . 3 3 2 2 . . . 2 2 1 1 . . . 1 1 ] \begin{bmatrix}\lfloor \frac{m}{d}\rfloor&\lfloor \frac{m}{d}\rfloor&...&\lfloor \frac{m}{d}\rfloor & \lfloor \frac{m}{d}\rfloor\\ ...&...&...&...&... \\3&3&...&3&3\\2&2&...&2&2\\1&1&...&1&1\\ \end{bmatrix} ⎣⎢⎢⎢⎢⎡⌊dm⌋...321⌊dm⌋...321...............⌊dm⌋...321⌊dm⌋...321⎦⎥⎥⎥⎥⎤
由分配律,
∑ ( a 1 a 2 ⋯ a n ) k = ( ∑ i = 1 ⌊ m d ⌋ i k ) n \sum(a_{1}a_{2} \cdots a_{n})^{k}=\bigg(\sum_{i=1}^{\lfloor \frac{m}{d}\rfloor}i^k\bigg)^n ∑(a1a2⋯an)k=(i=1∑⌊dm⌋ik)n
考虑到 gcd ( a 1 , a 2 , ⋯ , a n ) ≠ 1 \gcd(a_{1},a_{2},\cdots,a_{n})\not= 1 gcd(a1,a2,⋯,an)=1 的情况,我们容易发现这是一个和约数有关的容斥原理,即容斥系数应当是莫比乌斯函数!
详细证明见:XMU区域赛选拔 D.塔子哥数数
对于 gcd ( a 1 , a 2 , ⋯ , a n ) = b \gcd(a_{1},a_{2},\cdots,a_{n})= b gcd(a1,a2,⋯,an)=b, 剩下可选的数:
[ ⌊ m b d ⌋ ⌊ m b d ⌋ . . . ⌊ m b d ⌋ ⌊ m b d ⌋ . . . . . . . . . . . . . . . 3 b 3 b . . . 3 b 3 b 2 b 2 b . . . 2 b 2 b b b . . . b b ] \begin{bmatrix}\lfloor \frac{m}{bd}\rfloor&\lfloor \frac{m}{bd}\rfloor&...&\lfloor \frac{m}{bd}\rfloor & \lfloor \frac{m}{bd}\rfloor\\ ...&...&...&...&... \\3b&3b&...&3b&3b\\2b&2b&...&2b&2b\\b&b&...&b&b\\ \end{bmatrix} ⎣⎢⎢⎢⎢⎡⌊bdm⌋...3b2bb⌊bdm⌋...3b2bb...............⌊bdm⌋...3b2bb⌊bdm⌋...3b2bb⎦⎥⎥⎥⎥⎤
∑ ( a 1 a 2 ⋯ a n ) k = ( ( ∑ i = 1 ⌊ m b d ⌋ i k ) b k ) n \sum(a_{1}a_{2} \cdots a_{n})^{k}=\left(\bigg(\sum_{i=1}^{\lfloor \frac{m}{bd}\rfloor}i^k\bigg)b^k\right)^n ∑(a1a2⋯an)k=⎝⎛(i=1∑⌊bdm⌋ik)bk⎠⎞n
a n s = ( d k ) n ∑ i = 1 ⌊ m d ⌋ μ ( i ) ( ( ∑ j = 1 ⌊ m i d ⌋ j k ) i k ) n ans=(d^k)^n\sum_{i=1}^{\lfloor \frac{m}{d}\rfloor}\mu(i)\left(\bigg(\sum_{j=1}^{\lfloor \frac{m}{id}\rfloor}j^k\bigg)i^k\right)^n ans=(dk)ni=1∑⌊dm⌋μ(i)⎝⎛(j=1∑⌊idm⌋jk)ik⎠⎞n
我们注意到 n n n只出现于指数上,由扩展欧拉定理,可以在读入 n n n时对 φ ( m o d ) \varphi(mod) φ(mod)取模;对于每次询问,我们可以 O ( m ) O(m) O(m)预处理出 k 1 , k 2 , . . . , k m k^1,k^2,...,k^m k1,k2,...,km ,以及其前缀和。计算时,对于内层括号里的东西我们就可以 O ( 1 ) O(1) O(1)求,再跑一个快速幂,总体复杂度 O ( T ∗ m l o g n ) O(T*mlog_n) O(T∗mlogn)。
#include
using namespace std;
const int mod = 59964251;
const int phi = 59870352;
const int MAXN = 1e5 + 50;
int T, n, m, d, k;
char s[MAXN];
int maxup;
int powk[MAXN], sumpowk[MAXN];
int getmod(int mo)
{
int b = 0; char c;
while(!isdigit(c = getchar()));
for(; isdigit(c); c = getchar())
{
b = b * 10 + c - '0';
if(b >= mo) b %= mo;
}
return b;
}
inline int add(int a, int b)
{
int ret = a + b;
if(ret > mod) ret -= mod;
return ret;
}
int ksm(int a, int b)
{
int ret = 1;
for(; b; b >>= 1, a = 1LL * a * a % mod) if(b&1) ret = 1LL * ret * a % mod;
return ret;
}
int mu[MAXN], prime[MAXN], num[MAXN], tot;
void pre()
{
mu[1] = 1;
for(int i = 2; i < MAXN; i++)
{
if(!num[i])
{
prime[++tot] = i;
mu[i] = -1;
}
for(int j = 1; j <= tot && i * prime[j] < MAXN; j++)
{
num[i*prime[j]] = 1;
if(i % prime[j]) mu[i*prime[j]] = -mu[i];
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
void init()
{
maxup = m / d;
for(int i = 1; i <= maxup; i++) powk[i] = ksm(i, k);
for(int i = 1; i <= maxup; i++) sumpowk[i] = add(sumpowk[i-1], powk[i]);
}
void work()
{
int sum = 0;
for(int i = 1; i <= maxup; i++)
{
int tmp1 = maxup / i;
int tmp2 = 1LL * sumpowk[tmp1] * powk[i] % mod;
int tmp3 = ksm(tmp2, n);
(sum += mod + tmp3 * mu[i]) %= mod;
}
int b = 1LL * n * k % phi;
sum = 1LL * sum * ksm(d, b) % mod;
printf("%d\n", sum);
}
int main()
{
scanf("%d", &T);
pre();
while(T--)
{
n = getmod(phi);
if(!n) n = phi;
scanf("%d%d%d", &m, &d, &k);
k %= phi;
if(!k) k = phi;
init();
work();
}
return 0;
}
题目链接
Define the function
f a ( x ) = a x ( a > 0 ∧ a ≠ 1 ) \displaystyle f_a\left( x \right) = a^x~(a > 0 \wedge a \neq 1) fa(x)=ax (a>0∧a=1) for all x ∈ ( − ∞ , + ∞ ) x \in (-\infty, +\infty) x∈(−∞,+∞).
You are asked to calculate the value of
∑ a = 2 n ( a ∑ b = a n ⌊ f a − 1 ( b ) ⌋ ⌈ f b − 1 ( a ) ⌉ ) \displaystyle \sum_{a=2}^n{\left( a \sum_{b=a}^n{\lfloor f_{a}^{-1}\left( b \right) \rfloor}\lceil f_{b}^{-1}\left( a \right) \rceil \right)} a=2∑n(ab=a∑n⌊fa−1(b)⌋⌈fb−1(a)⌉)
where f a − 1 ( x ) f_a^{-1}\left( x \right) fa−1(x) is the inverse function of f a ( x ) f_a\left( x \right) fa(x), ⌊ x ⌋ \lfloor x \rfloor ⌊x⌋ is the largest integer that is less than or equal to x x x, and ⌈ x ⌉ \lceil x \rceil ⌈x⌉ is the smallest integer that is greater than or equal to x x x.
Since the value could be very large, please output the value modulo 998244353 998244353 998244353.
An integer n ( 2 ≤ n ≤ 1 0 12 ) n~(2 \leq n \leq 10^{12}) n (2≤n≤1012) described above.
An integer denotes the value you have calculated modulo 998244353 998244353 998244353.
2
2
10
236
由题意, f a − 1 ( x ) = l o g a x f_a^{-1}\left( x \right)=log_ax fa−1(x)=logax。因此当 a ≤ b a\leq b a≤b 时, ⌈ f b − 1 ( a ) ⌉ = 1 \lceil f_{b}^{-1}\left( a \right) \rceil=1 ⌈fb−1(a)⌉=1,即原式等于
∑ a = 2 n ( a ∑ b = a n ⌊ l o g a b ⌋ ) \displaystyle \sum_{a=2}^n{\left( a \sum_{b=a}^n{\lfloor log_ab \rfloor}\right)} a=2∑n(ab=a∑n⌊logab⌋)
当 a > n a>\sqrt n a>n时, ⌊ l o g a b ⌋ = 1 \lfloor log_ab \rfloor=1 ⌊logab⌋=1,
a ∑ b = a n ⌊ l o g a b ⌋ = a ∑ b = a n 1 = a ∗ ( n − a + 1 ) a \sum_{b=a}^n{\lfloor log_ab \rfloor}=a \sum_{b=a}^n{1}=a*(n-a+1) ab=a∑n⌊logab⌋=ab=a∑n1=a∗(n−a+1)
设 x = ⌊ n ⌋ x=\lfloor\sqrt n \rfloor x=⌊n⌋,则:
∑ a = x + 1 n ( a ∑ b = a n ⌊ l o g a b ⌋ ) \sum_{a=x+1}^n{\left( a \sum_{b=a}^n{\lfloor log_ab \rfloor}\right)} a=x+1∑n(ab=a∑n⌊logab⌋)
= ∑ a = x + 1 n a ∗ ( n − a + 1 ) =\sum_{a=x+1}^n{a*(n-a+1)} =a=x+1∑na∗(n−a+1)
= ∑ a = x + 1 n ( n + 1 ) a − a 2 =\sum_{a=x+1}^n{(n+1)a-a^2} =a=x+1∑n(n+1)a−a2
= ( n + 1 ) ( x + n + 1 ) ( n − x ) 2 − n ( n + 1 ) ( 2 n + 1 ) 6 + x ( x + 1 ) ( 2 x + 1 ) 6 =\frac{(n+1)(x+n+1)(n-x)}{2}-\frac{n(n+1)(2n+1)}{6}+\frac{x(x+1)(2x+1)}{6} =2(n+1)(x+n+1)(n−x)−6n(n+1)(2n+1)+6x(x+1)(2x+1)
当 a ≤ n a\leq\sqrt n a≤n时,即 a ≤ x a\leq x a≤x时,我们可以暴力统计每个 a a a的答案:
设 a k ≤ n , a k + 1 > n a^k\leq n, a^{k+1}>n ak≤n,ak+1>n。
当 a ≤ b ≤ a 2 − 1 a\leq b \leq a^2-1 a≤b≤a2−1时, ⌊ l o g a b ⌋ = 1 \lfloor log_ab \rfloor=1 ⌊logab⌋=1,共 a 2 − a a^2-a a2−a个;
当 a 2 ≤ b ≤ a 3 − 1 a^2\leq b \leq a^3-1 a2≤b≤a3−1时, ⌊ l o g a b ⌋ = 2 \lfloor log_ab \rfloor=2 ⌊logab⌋=2,共 a 3 − a 2 a^3-a^2 a3−a2个;
…
当 a k − 1 ≤ b ≤ a k − 1 a^{k-1}\leq b \leq a^k-1 ak−1≤b≤ak−1时, ⌊ l o g a b ⌋ = k − 1 \lfloor log_ab \rfloor=k-1 ⌊logab⌋=k−1,共 a k − a k − 1 a^k-a^{k-1} ak−ak−1个;
当 a 2 ≤ b ≤ n a^2\leq b \leq n a2≤b≤n时, ⌊ l o g a b ⌋ = k \lfloor log_ab \rfloor=k ⌊logab⌋=k,共 n − a k + 1 n-a^k+1 n−ak+1个;
∑ b = a n ⌊ l o g a b ⌋ \sum_{b=a}^n{\lfloor log_ab \rfloor} b=a∑n⌊logab⌋
= ( k − 1 ) a k − ( a + a 2 + . . . + a k − 1 ) + k ( n − a k + 1 ) =(k-1)a^k-(a+a^2+...+a^{k-1})+k(n-a^k+1) =(k−1)ak−(a+a2+...+ak−1)+k(n−ak+1)
= k ( n + 1 ) − a ( a k − 1 ) a − 1 =k(n+1)-\frac{a(a^k-1)}{a-1} =k(n+1)−a−1a(ak−1)
a n s = ans= ans=
∑ a = 1 x ( k ( n + 1 ) − a ( a k − 1 ) a − 1 ) + ( n + 1 ) ( x + n + 1 ) ( n − x ) 2 − n ( n + 1 ) ( 2 n + 1 ) 6 + x ( x + 1 ) ( 2 x + 1 ) 6 \sum_{a=1}^{x}\left(k(n+1)-\frac{a(a^k-1)}{a-1}\right)+\\\frac{(n+1)(x+n+1)(n-x)}{2}-\frac{n(n+1)(2n+1)}{6}+\frac{x(x+1)(2x+1)}{6} a=1∑x(k(n+1)−a−1a(ak−1))+2(n+1)(x+n+1)(n−x)−6n(n+1)(2n+1)+6x(x+1)(2x+1)
#include
using namespace std;
typedef long long ll;
const int mod = 998244353;
int inv2, inv6;
int ans;
int b;
ll n;
int ksm(int a, int b)
{
int ret = 1;
for(; b; b >>= 1, a = 1LL * a * a % mod)
{
if(b & 1) ret = 1LL * ret * a % mod;
}
return ret;
}
int ni(int a)
{
return ksm(a, mod - 2);
}
void init()
{
int tmp1 = (n+1) % mod, tmp2 = (n+b+1) % mod, tmp3 = (n-b+mod) % mod;
int tmp4 = n % mod, tmp5 = (n+1) % mod, tmp6 = (2*n+1) % mod;
ans = 1LL * tmp1 * tmp2 % mod * tmp3 % mod * inv2 % mod;
(ans += 1LL * b * (b+1) % mod * (2*b+1) % mod * inv6 % mod) %= mod;
(ans += mod - 1LL * tmp4 * tmp5 % mod * tmp6 % mod * inv6 % mod) %= mod;
}
void work()
{
for(int i = 2; i <= b; i++)
{
int k = 1; ll tmp = i;
while(tmp < n)
{
tmp *= i;
k++;
}
if(tmp > n) k--;
int tmp1 = (n+1) % mod * k % mod;
int tmp2 = 1LL * i * (ksm(i, k) - 1 + mod) % mod * ni(i-1) % mod;
(ans += 1LL * (tmp1 - tmp2 + mod) * i % mod) %= mod;
}
}
int main()
{
inv2 = ni(2); inv6 = ni(6);
scanf("%lld", &n);
if(n == 2) {printf("2\n"); return 0;}
if(n == 3) {printf("7\n"); return 0;}
b = sqrt(n);
init();
work();
printf("%d\n", ans);
return 0;
}
题目链接
Little Q is very sleepy, and he really needs some coffee to make him awake. At this time, Little L brings a pot to Little Q, and he states the pot as follows.
For a prime number p p p, if p m ∣ n p^m | n pm∣n and p m + 1 ∤ n p^{m+1}\not | n pm+1∣n, we say pot p ( n ) = m \text{pot}_p(n)=m potp(n)=m.
The pot is very special that it can make everyone awake immediately.
Now Little L provides n ( 1 ≤ n ≤ 1 0 5 ) n~(1 \le n \le 10^5) n (1≤n≤105) integers a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an to Little Q, each of which is 1 1 1 initially. After that, Little L shows 2 2 2 types of queries:
MULTIPLY l r x : For every i ∈ [ l , r ] i \in [l,r] i∈[l,r] ( 1 ≤ l ≤ r ≤ n ) (1\le l\le r\le n) (1≤l≤r≤n), multiply a i a_i ai by x x x ( 2 ≤ x ≤ 10 ) (2 \le x \le 10) (2≤x≤10).
MAX l r : Calculate the value of
max l ≤ i ≤ r { max p ∣ a i { pot p ( a i ) } } ( 1 ≤ l ≤ r ≤ n ) , \displaystyle \max_{l\le i\le r} \left\{ \max_{p|a_i} \left\{ \text{pot}_p (a_i) \right\} \right\}~(1 \le l \le r \le n), l≤i≤rmax{p∣aimax{potp(ai)}} (1≤l≤r≤n),
where p p p is prime.
Now you need to perform q ( 1 ≤ q ≤ 1 0 5 ) q~(1 \le q \le 10^5) q (1≤q≤105) queries of these two types of queries described above.
If you perform a “MULTIPLY” query, you don’t need to output anything.
If you perform a “MAX” query, you need to output a line like ANSWER y, where y y y the value you’ve calculated.
给你 n n n个初始值为 1 1 1的数, 每次选取一个区间 [ l , r ] [l, r] [l,r], 进行其中一种操作:区间所有的数全都乘以 x x x ( 2 ≤ x ≤ 10 ) (2 \le x \le 10) (2≤x≤10);求区间这些数中,分解质因数后单个质数的次数最高为多少。
The first line contains two integers n ( 1 ≤ n ≤ 1 0 5 ) n~(1 \le n \le 10^5) n (1≤n≤105) and q ( 1 ≤ q ≤ 1 0 5 ) q~(1 \le q \le 10^5) q (1≤q≤105), the number of integers and the number of queries.
Each of the next q q q lines contains one type of query described above.
Output
For each “MAX” query, output one line in the format of ANSWER y, where y y y the value you have calculated.
5 6
MULTIPLY 3 5 2
MULTIPLY 2 5 3
MAX 1 5
MULTIPLY 1 4 2
MULTIPLY 2 5 5
MAX 3 5
ANSWER 1
ANSWER 2
If m m m and n n n are non-zero integers, or more generally, non-zero elements of an integral domain, it is said that m m m divides n n n if there exists an integer k k k, or an element k k k of the integral domain, such that m × k = n m \times k=n m×k=n, and this is written as m ∣ n m \mid n m∣n.
注意到10以内的质数只有2,3,5,7,因此对它们分别维护一棵支持区间加法、区间取最大值的线段树即可。
#include
using namespace std;
const int MAXN = 1e5 + 50;
int n, q;
char s[10];
#define ls (2*rt)
#define rs (2*rt+1)
#define mid ((l+r)>>1)
struct Node
{
int mx, tag;
}t[4][MAXN << 2];
void pushdown(int p, int rt)
{
if(t[p][rt].tag)
{
int x = t[p][rt].tag;
t[p][rt].tag = 0;
t[p][ls].tag += x;
t[p][rs].tag += x;
t[p][ls].mx += x;
t[p][rs].mx += x;
}
}
void pushup(int p, int rt)
{
t[p][rt].mx = max(t[p][ls].mx, t[p][rs].mx);
}
void add(int p, int rt, int l, int r, int L, int R, int x)
{
if(r < L || l > R) return;
if(l >= L && r <= R)
{
t[p][rt].mx += x;
t[p][rt].tag += x;
return;
}
pushdown(p, rt);
add(p, ls, l, mid, L, R, x);
add(p, rs, mid+1, r, L, R, x);
pushup(p, rt);
}
int ask(int p, int rt, int l, int r, int L, int R)
{
if(r < L || l > R) return 0;
if(l >= L && r <= R) return t[p][rt].mx;
pushdown(p, rt);
return max(ask(p, ls, l, mid, L, R), ask(p, rs, mid+1, r, L, R));
}
void update(int x, int L, int R)
{
if(x == 2) add(0, 1, 1, n, L, R, 1);
if (x == 3) add(1, 1, 1, n, L, R, 1);
if (x == 4) add(0, 1, 1, n, L, R, 2);
if (x == 5) add(2, 1, 1, n, L, R, 1);
if (x == 6)
{
add(1, 1, 1, n, L, R, 1);
add(0, 1, 1, n, L, R, 1);
}
if (x == 7) add(3, 1, 1, n, L, R, 1);
if (x == 8) add(0, 1, 1, n, L, R, 3);
if (x == 9) add(1, 1, 1, n, L, R, 2);
if (x == 10)
{
add(0, 1, 1, n, L, R, 1);
add(2, 1, 1, n, L, R, 1);
}
}
int query(int L, int R)
{
int m1, m2, m3, m4;
m1 = ask(0, 1, 1, n, L, R);
m2 = ask(1, 1, 1, n, L, R);
m3 = ask(2, 1, 1, n, L, R);
m4 = ask(3, 1, 1, n, L, R);
return max(max(m1, m2), max(m3, m4));
}
int main()
{
scanf("%d%d", &n, &q);
for(int i = 1; i <= q; i++)
{
int x, L, R;
scanf("%s", s);
if(s[1] == 'U')
{
scanf("%d%d%d", &L, &R, &x);
update(x, L, R);
}
else
{
scanf("%d%d", &L, &R);
printf("ANSWER %d\n", query(L, R));
}
}
return 0;
}
题目链接
BZOJ2200原题!样例都一样!出题组锅背好!
Pony is the boss of a courier company. The company needs to deliver packages to n n n offices numbered from 1 1 1 to n n n. Especially, the ss-th office is the transfer station of the courier company.
There are x x x ordinary two-way roads and y y y one-way roads between these offices. The delivery vans will consume c i c_i ci power if they pass through the i i i-th road. In general, the power consumption on one road must be non-negative. However, thanks to the experimental charging rail, the consumption may be negative on some one-way roads.
Besides, Pony got the following public information. The relevant department promised that if there is a one-way street from a i a_i ai to b i b_i bi, it is impossible to return from b i b_i bi to a i a_i ai.
To avoid the delivery vans anchoring on the road, Xiaodao wants to find these lowest power consumptions from the transfer station to these offices.
给你一幅图,有 x x x条无向边和 y y y条有向边。其中无向变的权值均为正,有向边的权值可能为负。保证如果从 a i a_i ai到 b i b_i bi有一条有向边,则不存在 b i b_i bi到 a i a_i ai的路径。给你一个出发点,求单源最短路径。
The first line contains four integers n ( 1 ≤ n ≤ 25000 ) , x , y ( 1 ≤ x , y ≤ 50000 ) n~(1 \le n \le 25000), x, y~(1 \le x, y \le 50000) n (1≤n≤25000),x,y (1≤x,y≤50000), and s ( 1 ≤ s ≤ n ) s~(1 \le s \le n) s (1≤s≤n). This is followed by x + y x+y x+y lines, each line of which contains three integer a i , b i ( 1 ≤ a i , b i ≤ n , a i ≠ b i ) a_i, b_i~(1 \le a_i, b_i \le n, a_i \neq b_i) ai,bi (1≤ai,bi≤n,ai=bi) and c i ( − 10000 ≤ c i ≤ 10000 ) c_i~(-10000 \le c_i \le 10000) ci (−10000≤ci≤10000) describing the roads. The first x x x given roads are ordinary two-way roads, and the last y y y given roads are one-way roads.
The output should contain nn lines, the ii-th line represents the minimum energy consumption from ss-th to the ii-th office if possible, or output NO PATH if it is impossible to reach the i i i-th office.
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
样例输出
NO PATH
NO PATH
5
0
-95
-100
首先,由于存在负权路径,直接Dijkstra显然不可取。考虑使用spfa,又很容易被卡掉。我们观察题目比起裸的单源最短路径有何区别:将无向图的每个联通块缩成点后,形成了一个拓扑图!
于是我们可以先用dfs对所有的联通块染色,按照拓扑排序的顺序,对每个联通块内部用Dijkstra。如果一条边连向另一个联通块,就更新其该点的最短路径(但不加入堆中),并且让目标联通块的入度 − 1 -1 −1。
#include
using namespace std;
int n, x, y, s;
const int MAXN = 2e5 + 50;
typedef pair<int, int> pii;
#define mp make_pair
int head[MAXN], tot;
struct Edge
{
int nex, to, dis;
}eg[MAXN];
void addedge(int a, int b, int c)
{
eg[++tot] = {head[a], b, c};
head[a] = tot;
}
void add(int a, int b, int c)
{
addedge(a, b, c);
addedge(b, a, c);
}
vector<int> bel[MAXN];
int co[MAXN], cnt;//联通块的颜色、联通块的数量
void dfs(int v, int col)//dfs给联通块染色
{
co[v] = col;
bel[col].push_back(v);
for(int i = head[v]; i; i = eg[i].nex)
{
int to = eg[i].to;
if(!co[to]) dfs(to, col);
}
}
int deg[MAXN], dis[MAXN];//每个联通块的入度、单源最短路径
int vis[MAXN];
queue<int> que;//拓扑排序:入度为0的联通块入队
priority_queue<pii, vector<pii>, greater<pii> > pq;
void Dijkstra()
{
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
for(int i = 1; i <= cnt; i++) if(!deg[i]) que.push(i);
while(!que.empty())//topological-sort
{
int u = que.front(); que.pop();
int sz = bel[u].size();
for(int i = 0; i < sz; i++) pq.push(mp(dis[bel[u][i]], bel[u][i]));
while(!pq.empty())//Dijkstra
{
int x = pq.top().second; pq.pop();
if(vis[x]) continue;
vis[x] = 1;
for(int i = head[x]; i; i = eg[i].nex)
{
int to = eg[i].to;
if(co[x] == co[to] && dis[to] > dis[x] + eg[i].dis)
{
dis[to] = dis[x] + eg[i].dis;
pq.push(mp(dis[to], to));
}
if(co[x] != co[to])
{
dis[to] = min(dis[to], dis[x] + eg[i].dis);
deg[co[to]]--;
if(!deg[co[to]]) que.push(co[to]);
}
}
}
}
}
int main()
{
scanf("%d%d%d%d", &n, &x, &y, &s);
for(int i = 1, a, b, c; i <= x; i++)
{
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
for(int i = 1; i <= n; i++) if(!co[i]) dfs(i, ++cnt);
for(int i = 1, a, b, c; i <= y; i++)
{
scanf("%d%d%d", &a, &b, &c);
addedge(a, b, c);
deg[co[b]]++;
}
Dijkstra();
for(int i = 1; i <=n; i++)
{
if(dis[i] > 1e9) puts("NO PATH");
else printf("%d\n", dis[i]);
}
return 0;
}
题目链接
As we already know, base64 is a common binary-to-text encoding scheme. Here we define a special series of positional systems that represent numbers using a base (a.k.a. radix) of 2 2 2 to 62 62 62. The symbols ‘ 0 0 0’ – ‘ 9 9 9’ represent zero to nine, and ‘A’ – ‘Z’ represent ten to thirty-five, and ‘a’ – ‘z’ represent thirty-six to sixty-one. Now you need to convert some integer z z z in base x x x into base y y y.
高精度进制转换:给你三个数 x , y , z x, y, z x,y,z,将一个 x x x进制的数 z z z转化为 y y y进制。其中’ 0 0 0’ – ‘ 9 9 9’ 代表 0 − 9 0-9 0−9, ‘A’ – ‘Z’ 代表 10 − 35 10-35 10−35, ‘a’ – ‘z’ 代表 36 − 61 36-61 36−61。
The input contains three integers x , y ( 2 ≤ x , y ≤ 62 ) x, y~(2 \le x, y \le 62) x,y (2≤x,y≤62) and z ( 0 ≤ z < x 120 ) z~(0 \le z < x^{120}) z (0≤z<x120), where the integer z z z is given in base x x x.
Output the integer z z z in base y y y.
16 2 FB
11111011
对于进制转换问题,我们可以利用短除法:重复记录 z % y z\%y z%y的值,并且将 z z z除 y y y。将得到的余数序列倒序输出即可。对于高进度取模,我们可以从高位算起依次将这一位对 y y y的余数给到后一位。
#include
using namespace std;
const int MAXN = 1500;
int x, y;
char s[MAXN], ans[MAXN];
int t[MAXN], res[MAXN];
int getnum(char c)//将字符转化为数字
{
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'A' && c <= 'Z') return c - 'A' + 10;
else return c - 'a' + 36;
}
char getch(int num)//将数字转化为字符
{
if(num <= 9) return num + '0';
if(num <= 35) return num + 'A' - 10;
else return num + 'a' - 36;
}
void work()
{
int len = (int)strlen(s+1);
for(int i = 1; i <= len; i++) t[i] = getnum(s[i]);
for(int j = 1, k = 0; j <= len; )//j为当前最高位
{
for(int i = j; i < len; i++)
{
t[i+1] += t[i] % y * x;
t[i] /= y;
}
res[++k] = t[len] % y;//得到此次除y的余数
t[len] /= y;
while(j <= len && !t[j]) j++;
for(int i = 1; i <= k; i++) ans[i] = getch(res[k-i+1]);
//倒序输出
}
}
int main()
{
scanf("%d%d%s", &x, &y, s+1);
work();
printf("%s\n", ans+1);
return 0;
}
题目链接
You are given two n × m n \times m n×m matrices, and the elements of each matrix are ranged from 1 1 1 to n × m n \times m n×m and pairwise distinct. You need to find the common submatrix with the largest size between these two matrices.
Example:
Matrix A:
1 2 3 4 5 6 8 7 9 \displaystyle \begin{array}{ccc} 1 & 2 & 3\\ 4 & 5 & 6\\ 8 & 7 & 9\\ \end{array} 148257369
Matrix B:
5 6 1 7 9 3 2 4 8 \displaystyle \begin{array}{ccc} 5 & 6 & 1\\ 7 & 9 & 3\\ 2 & 4 & 8\\ \end{array} 572694138
Largest common submatrix:
5 6 7 9 \displaystyle \begin{array}{cc} 5 & 6\\ 7 & 9\\ \end{array} 5769
给你两个 n × m n \times m n×m的矩阵,求它们的最大公共子矩阵。
The first line of input contains two integers n ( 1 ≤ n ≤ 1000 ) n~(1 \le n \le 1000) n (1≤n≤1000) and m ( 1 ≤ m ≤ 1000 ) m~(1 \le m \le 1000) m (1≤m≤1000), denoting the number of rows and columns of each matrix.
Each of the next nn lines contain mm integers per line, denoting the first matrix A = ( a i , j ) n × m A=(a_{i,j})_{n\times m} A=(ai,j)n×m. And again, each of the next n n n lines contains mm integers per line, denoting the second matrix B = ( b i , j ) n × m B=(b_{i,j})_{n\times m} B=(bi,j)n×m
It is guaranteed that 1 ≤ a i , j , b i , j ≤ n × m 1 \le a_{i,j}, b_{i,j} \le n \times m 1≤ai,j,bi,j≤n×m, and a i 1 , j 1 ≠ a i 2 , j 2 ∧ b i 1 , j 1 ≠ b i 2 , j 2 a_{i_1,j_1} \ne a_{i_2,j_2} \wedge b_{i_1,j_1} \ne b_{i_2,j_2} ai1,j1=ai2,j2∧bi1,j1=bi2,j2 always holds for each pair of ( i 1 , j 1 ) (i_1, j_1) (i1,j1) and ( i 2 , j 2 ) (i_2, j_2) (i2,j2), where i 1 ≠ i 2 ∨ j 1 ≠ j 2 i_1 \ne i_2 \vee j_1 \ne j_2 i1=i2∨j1=j2.
Output an integer representing the size of the largest common submatrix.
3 4
5 6 7 8
1 2 3 4
9 10 11 12
5 6 8 7
1 2 4 3
12 11 10 9
4
Largest common submatrix in the sample test:
5 6 1 2 \displaystyle \begin{array}{cc} 5 & 6\\ 1 & 2\\ \end{array} 5162
我们首先可以将两个矩阵建立一个映射关系:将第一个矩阵按照行优先的顺序从新标号,并且将第二个矩阵中的每个数变成矩阵1的相应新标号。如样例中,我们把第二个矩阵变成了:
1 2 3 4 5 6 8 7 12 11 10 9 \displaystyle \begin{array}{cc} 1&2&3&4\\ 5&6&8&7\\ 12&11&10&9\\ \end{array} 151226113810479
问题就转化成得到的新矩阵中,满足“右边元素比左边元素大1,下边元素比上边元素大m”的最大子矩阵。这个问题可用悬线法解决。
可以参考这道题
定义:
l [ i ] [ j ] l[i][j] l[i][j]: 代表从 ( i , j ) (i,j) (i,j)能到达的最左位置
r [ i ] [ j ] r[i][j] r[i][j]: 代表从 ( i , j ) (i,j) (i,j)能到达的最右位置
u [ i ] [ j ] u[i][j] u[i][j]: 代表从 ( i , j ) (i,j) (i,j)向上扩展最长长度.
递推公式:
l [ i ] [ j ] = m a x ( l [ i ] [ j ] , l [ i − 1 ] [ j ] ) r [ i ] [ j ] = m i n ( r [ i ] [ j ] , r [ i − 1 ] [ j ] ) u [ i ] [ j ] = u [ i − 1 ] [ j ] + 1 ; l[i][j]=max(l[i][j], l[i-1][j])\\ r[i][j]=min(r[i][j], r[i-1][j])\\ u[i][j] = u[i-1][j] + 1; l[i][j]=max(l[i][j],l[i−1][j])r[i][j]=min(r[i][j],r[i−1][j])u[i][j]=u[i−1][j]+1;
#include
using namespace std;
const int MAXN = 1005;
int n, m;
int a[MAXN][MAXN], b[MAXN * MAXN];
int l[MAXN][MAXN], r[MAXN][MAXN], u[MAXN][MAXN];
int ans;
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1, x; i <= n*m; i++)
{
scanf("%d", &x);
b[x] = i;
}
for(int i = 1; i <= n; i++)
{
for(int j = 1, x; j <= m; j++)
{
scanf("%d", &x);
a[i][j] = b[x];
l[i][j] = r[i][j] = j;
u[i][j] = 1;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 2; j <= m; j++)
{
if(a[i][j] == a[i][j-1] + 1) l[i][j] = l[i][j-1];
}
for(int j = m-1; j; j--)
{
if(a[i][j] == a[i][j+1] - 1) r[i][j] = r[i][j+1];
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(i > 1 && a[i][j] == a[i-1][j] + m)
{
l[i][j] = max(l[i][j], l[i-1][j]);
r[i][j] = min(r[i][j], r[i-1][j]);
u[i][j] = u[i-1][j] + 1;
}
int x = r[i][j] - l[i][j] + 1;
ans = max(ans, x*u[i][j]);
}
}
printf("%d\n", ans);
return 0;
}
题目链接
The Fibonacci sequence is a sequence of natural numbers, and is defined as follows:
F 1 = 1 F_1=1 F1=1;
F 2 = 1 F_2=1 F2=1; and
F n = F n − 1 + F n − 2 F_n=F_{n-1}+F_{n-2} Fn=Fn−1+Fn−2 for n > 2 n>2 n>2.
Write a program to output the first 5 5 5 numbers in the Fibonacci sequence.
There is no input for this problem.
Output 55 integers indicating the first 55 numbers in the Fibonacci sequence. Any two adjacent numbers in the output are separated by exactly one space and there is no extra space or symbol at the end of the line.
(no input)
1 1 2 3 5
签到题不多说。
#include
int main()
{
std::cout << "1 1 2 3 5" << std::endl;
return 0;
}