CodeCraft-20 (Div. 2)
前言
比赛AC
简明题意
有n个人,每个人有个分数,最高分是m。现在其中一个同学可以修改所有人的分数,他想使得最高分不超过m且平均分不变的情况下尽可能把自己分数修改高。问最高是多少。
正文
平均分不变,等价于总分不变。直接让自己的分等于总分,其他人都0分就可以。然后和m比一下,如果比m大了就是m,否则就是总分。
代码
简明题意
有一个长度n<=5000的字符串,现在可以选一个k(1<=k<=n),选了k之后会依次反转原字符串的1到k,2到k+1…最终得到新的字符串。问k选几时,得到的新字符串字典序最小。
正文
k=2时,相当于冒泡排序,就是把a[1]移到了最后。
k>=2时,把1-k-1看成一个整体,这个整体会被移动到最后面。但注意每反转一次,那个整体的顺序就被颠倒一次。一共会被反转n-k+1次,所以当n-k+1是奇数时,就应该反转那个整体。
所以对于每个K就能O(1)得出操作后的字符串,而1<=k<=n,相当于一个字符串O(n)就能找到答案,复杂度是够的。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;
void solve ( )
{
int t;
cin >> t;
while ( t-- )
{
int n;
cin >> n;
string a;
cin >> a;
string ans;
int min_k;
for ( int k = 1 ; k <= n; k++ )
{
string x = a. substr ( 0 , k - 1 ) ;
if ( ( n - k + 1 ) % 2 == 1 ) reverse ( x. begin ( ) , x. end ( ) ) ;
string y = a. substr ( k - 1 , n - k + 1 ) ;
string b = y + x;
if ( ans == "" ) ans = b, min_k = k;
else if ( b < ans) ans = b, min_k = k;
}
cout << ans << endl;
cout << min_k << endl;
}
}
int main ( )
{
solve ( ) ;
return 0 ;
}
赛后补题
简明题意
给你两个多项式f(x)和g(x),用数组a[]给出f(x)的系数,b[]给出g(x)的系数。给出质数p,令h(x)=f(x)*g(x),现在需要你输出h(x)的任意一个不能被p整除的系数。
a数组两两互质,b数组也是。
正文
首先得直到两个多项式乘出来是什么。假设有k和l,那么 c x + y = ∏ i = 0 x + y a i b x + y = a 0 b x + y + a 1 b x + y − 1 + . . . + a x b y + . . . + a x + 1 b y − 1 + a x + y b 0 c_{x+y}=\prod_{i=0}^{x+y}a_ib_{x+y}=a_0b_{x+y}+a_1b_{x+y-1}+...+a_xb_y+...+a_{x+1}b_{y-1}+a_{x+y}b_0 c x + y = i = 0 ∏ x + y