2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)
提交OJ:http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/13/
题号:xtu 1243-1252
xtu 1243 A题 2016
Given a 2×2 matrix
find An where A1=A,An=A×An−1. As the result may be large, you are going to find only the remainder after division by 7.
Special Note: The problem is intended to be easy. Feel free to think why the problem is called 2016
if you either:
The input contains at most 40 sets. For each set:
The first line contains an integer n (1≤n<10100000).
The second line contains 2 integers a11,a12.
The third line contains 2 integers a21,a22.
(0≤aij<7, (a11a22−a12a21) is not a multiple of 7)
For each set, a 2×2 matrix denotes the remainder of An after division by 7.
2
1 1
1 2
2016
1 1
1 2
2 3 3 5 1 0 0 1
思路:大数取模+矩阵乘法;
AC代码:
#include#include <string.h> const int M=500000; int a[M][2][2]; char s[M]; int main() { int n; while(scanf("%s",s)!=EOF) { int mod=0,n=0,x1,y1,x2,y2,len=strlen(s); scanf("%d %d %d %d",&x1,&y1,&x2,&y2); a[1][0][0]=a[0][0][0]=x1; a[1][0][1]=a[0][0][1]=y1; a[1][1][0]=a[0][1][0]=x2; a[1][1][1]=a[0][1][1]=y2; for(int i=2;i<=M;i++) { mod++; a[i][0][0]=(a[i-1][0][0]*x1+a[i-1][0][1]*x2)%7; a[i][0][1]=(a[i-1][0][0]*y1+a[i-1][0][1]*y2)%7; a[i][1][0]=(a[i-1][1][0]*x1+a[i-1][1][1]*x2)%7; a[i][1][1]=(a[i-1][1][0]*y1+a[i-1][1][1]*y2)%7; if(a[i][0][0]==x1&&a[i][0][1]==y1&&a[i][1][0]==x2&&a[i][1][1]==y2) break; } a[0][0][0]=a[mod][0][0]; a[0][0][1]=a[mod][0][1]; a[0][1][0]=a[mod][1][0]; a[0][1][1]=a[mod][1][1]; for(int i=0;i =(n*10+s[i]-'0')%mod; printf("%d %d\n%d %d\n",a[n%mod][0][0],a[n%mod][0][1],a[n%mod][1][0],a[n%mod][1][1]); } return 0; }) n
xtu 1244 B题 Gambling
In ICPCCamp, gambling is conducted as follow. A player will draw balls from an opaque bag containing a red balls, b green balls and c blue balls initially. Balls in the bag will be drawn in equal probability while drawn balls won't be put back into the bag. The player continues the process until he collects all a red balls, or all b green balls, or all c blue balls. He ends up with First Prize if he collects a red balls, or Second Prize if he collects b green balls, or Third Prize otherwise.
Bobo is going to take part in the above gambling. Therefore, it is very important for him to work out the probability of winning each prize.
The input contains at most 40 sets. For each set:
Three integers a,b,c (1≤a,b,c≤103).
For each set, three irreducible fractions pA,pB,pC denote the probability of winning First Price, Second Price, and Third Price, respectively.
1 1 1
1 2 3
1/3 1/3 1/3 7/12 4/15 3/20
题意:
有a个红球,b个绿球,c个黄球,先拿完a个红球一等奖,先拿完b个绿球二等奖,c个黄球三等奖。求各个奖获奖的概率。
思路:
分析首先拿完红球,即拿一等奖的概率:
我们假设拿完红球后继续拿,也就是拿完所有的球。
接下来逆向思考,红球不可能是最后一个,最后一个只可能是黄球或绿球,我们可以把摸出来的球的顺序逆置,比如(红,黄,红,绿,绿,黄,绿)逆置之后就是(绿,黄,绿,绿,红,黄,红),你会发现,你第一个摸到的球的颜色一定会是黄、绿当中的一种,而摸到的第二种颜色的球一定是黄绿当中未摸到过的,这样的话就很好计算了。
那么如果最后一个球是黄球,它的概率就是c/(a+b+c),除去黄球,最后一个是绿球的概率就是b/(a+b)。此时概率就是两者相乘。
最后一个球是绿球的话也是这样分析。
二等奖和三等奖也如上分析即可。
AC代码 :
#include
#include
#include
#include
using namespace std;
typedef long long LL;
LL a,b,c;
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
void cacl(LL a, LL b, LL c,int flag)
{
LL z=b*c*(2*a+b+c);
LL m=(a+b+c)*(a+b)*(a+c);
LL g=gcd(m,z);
printf("%I64d/%I64d",z/g,m/g);
if(flag<=2) printf(" ");
else printf("\n");
}
int main()
{
while(~scanf("%lld%lld%lld",&a,&b,&c))
{
cacl(a,b,c,1);
cacl(b,a,c,2);
cacl(c,a,b,3);
}
return 0;
}
xtu 1245 C题 Hamiltonian Path
In ICPCCamp, there are n cities and m directed roads between cities. The i-th road going from the ai-th city to the bi-th city is ci kilometers long. For each pair of cities (u,v), there can be more than one roads from u to v.
Bobo wants to make big news by solving the famous Hamiltonian Path problem. That is, he would like to visit all the n cities one by one so that the total distance travelled is minimized.
Formally, Bobo likes to find n distinct integers p1,p2,…,pn to minimize w(p1,p2)+w(p2,p3)+⋯+w(pn−1,pn) where w(x,y) is the length of road from the x-th city to the y-th city.
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (2≤n≤105,0≤m≤105).
The i-th of the following m lines contains 3 integers ai,bi,ci (1≤ai<bi≤n,1≤ci≤104).
For each set, an integer denotes the minimum total distance. If there exists no plan, output -1
instead.
3 3
1 2 1
1 3 1
2 3 1
3 2
1 2 1
1 3 2
2 -1
思路:只能1-2-3-4-。。。-n;1≤ai<bi≤n。。。
AC代码:
#include
#include
#include
#include
using namespace std;
const int M=100000+10;
int a[M];
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(a,0,sizeof(a));
int sum=0,k=0;
for(int i=1;i<=m;i++)
{
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
if(y==x+1)
{
if(a[x]==0)
{
a[x]=c;
k++;
}
else
a[x]=min(a[x],c);
}
}
if(k
xtu 1246 D题 Heartstone
Heartstone
Bobo is playing Heartstone. There are n minions in the battlefield. The i-th minion has hi hit points (HP).
Bobo uses two kinds of magic. The one is Arcane Shot and the other is Frostbolt. Arcane Shot can deal two points damage to a minion (that is to decrease the minion's HP by two), while Frostbolt can deal three points damage. A minion is killed when its HP is less or equal to zero.
Let f(a) be the minimum number of Frostbolt(s) required to kill all minions, if no more than a Arcane Shot(s) are used. Bobo would like to find out f(0)+f(1)+⋯+f(m) modulo (109+7).
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (1≤n≤105,0≤m≤105).
The second line contains n integers h1,h2,…,hn (1≤hi≤104).
For each set, an integer denotes f(0)+f(1)+⋯+f(m) modulo (109+7).
3 2
1 2 3
3 2
2 2 2
6 6
题意+思路(借鉴他人):
炉石游戏,有A 和F魔法,问给你n个带血量的小兵,你在每次最多拥有f(0)…f(m)个A魔法,f(0)代表最多有0个A魔法,的情况下,最少需要几个F魔法才能击杀所有的小兵
要控制魔法F的使用就要控制好A魔法的使用,优先队列加栈,x%3小的优先,x%3相等时,小的优先。
#include
#include
#include
#include
#include
#include
#include
#include
xtu 1247 E题 Pair - pair
Bobo is tired of all kinds of hard LIS (Longest Increasing Subsequence) problems, so he decides to make himself some easier one.
Bobo has n pairs (a1,b1),(a2,b2),…,(an,bn) where 1≤ai,bi≤m holds for all i. He defines f(i,j) be the length of longest increasing subsequence of sequence {ai,bi,aj,bj}.
It's clear that 1≤f(i,j)≤4. Bobo would like to know g(k) which is the number of pairs (i,j) where f(i,j)=k.
Note that a sequence labeled with {i1,i2,…,ik} is an increasing subsequence of {a1,a2,…,an} only if:
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (1≤n≤105,1≤m≤103).
The i-th of the following n lines contains 2 integers ai,bi (1≤ai,bi≤m).
For each set, 4 integers g(1),g(2),g(3),g(4).
2 4
1 2
3 4
2 1
1 1
1 1
0 3 0 1
4 0 0 0
分析:开个1000*1000的数组,预处理矩阵和,然后分类讨论就好(借鉴他人)
#include
#include
#include
#include
#include
#include
xtu 1248 F题 Tc or CF
TC or CF
There are n contests going to be held in the upcoming year. However, the committee keeps debating whether the contest is of TC (Thinking Creatively) style or CF (Coding Fast) style.
The committee knows in advance that there are m contestants who take part in exactly two contests. The i-th contestant will join the ai-th contest and then the bi-th contest. Note that contests are held in parallel so that there may exist two contestants i and j where ai=bj,bi=aj.
If the i-th contestant takes a TC-style contest then a CF-style contest, he or she will feel ci points of unhappiness. Otherwise he will not feel unhappy. Therefore, the committee will decides the types of contests according to the following 3 rules:
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (6≤n≤50,0≤m≤500).
The i-th of the following m lines contains 3 integers ai,bi,ci (1≤ai,bi≤n,ai≠bi,1≤ci≤1000).
For each set, an integer denotes the minimum of total unhappiness.
6 5
1 6 100
1 3 1
1 4 1
2 3 1
2 4 1
6 12
2 3 1
2 4 1
2 5 1
3 2 1
3 4 1
3 5 1
4 2 1
4 3 1
4 5 1
5 2 1
5 3 1
5 4 1
此题暂时无代码
xtu 1249 G题 Rolling Variance
Bobo learnt that the variance of a sequence a1,a2,…,an is
where
Bobo has a sequence a1,a2,…,an, and he would like to find the variance of each consecutive subsequences of length m. Formally, the i-th (1≤i≤n−m+1) rolling variance ri is the variance of sequence {ai,ai+1,…,ai+m−1}.
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (2≤m≤n≤105).
The second line contains n integers a1,a2,…,an (|ai|≤100).
For each set, (n−m+1) lines with floating numbers r1,r2,…,rn−m+1.
Your answer will be considered correct if its absolute or relative error does not exceed 10−4.
3 2
1 3 2
5 3
1 3 2 4 5
1.41421356
0.70710678
1.00000000
1.00000000
1.52752523
思路:前缀和
AC代码:
#include
#include
#include
#include
using namespace std;
const int M=100000+10;
double a[M],b[M];
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
a[0]=b[0]=0;
for(int i=1;i<=n;i++)
{
double x;
scanf("%lf",&x);
a[i]=a[i-1]+x;
b[i]=b[i-1]+x*x;
}
for(int i=m;i<=n;i++)
{
double av=0,s=0;
av=((a[i]-a[i-m])/(1.0*m));
s=((b[i]-b[i-m])+m*av*av-2*av*(a[i]-a[i-m]))/(m-1);
printf("%.8lf\n",sqrt(s));
}
}
return 0;
}
xtu 1250 H题 Super Fast Fourier Transform
Bobo has two sequences of integers {a1,a2,…,an} and {b1,b2,…,bm}. He would like to find
Note that ⌊x⌋ denotes the maximum integer does not exceed x, and |x| denotes the absolute value of x.
The input contains at most 30 sets. For each set:
The first line contains 2 integers n,m (1≤n,m≤105).
The second line contains n integers a1,a2,…,an.
The thrid line contains m integers b1,b2,…,bm.
(ai,bi≥0,a1+a2+⋯+an,b1+b2+…,bm≤106)
For each set, an integer denotes the sum.
1 2
1
2 3
2 3
1 2
3 4 5
2
7
思路:不同的数最多1000个,c++11交
AC 代码:
#include
#include
#include
#include
#include
using namespace std;
const int M=1000000+10;
int a[M],b[M],c[M],d[M];
typedef long long ll;
ll sum=0;
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
int k1=0,k2=0;
sum=0;
for(int i=0;i
xtu 1251 I题 Substring Query
Given a string s1,s2,…,sn of length n, Bobo is going to perform q operations of the following 2 kinds:
Find out the result of each opeartion of the second kind.
The input contains at most 10 sets. For each set:
The first line contains 2 integers n,q (1≤n≤5×104,1≤q≤105).
The second line contains a string s1s2…,sn of lowercase characters.
The i-th of the last q lines may: 1. contains an integer ki and a lowercase character ci, which denote an operation to change the ski into ci (1≤ki≤n). 2. contains an 0 followed by a string p1,p2,…,pli of lowercase characters, which denote an operation to query the number of times that p1,p2,…,pli occurs as a substring (li≥1,∑ili≤5×104).
For each operation of second kind in each set, an integer denotes the number of substrings.
5 5
aaaaa
0 aa
2 b
0 aba
4 b
0 aba
1 1
a
0 a
4
1
2
1
分析:AC自动机+分块
AC代码:
#include
using namespace std ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 100005 ;
const int MAXQ = 100005 ;
const int SQR1 = 128 ;
const int SQR2 = 256 ;
vector < int > G[MAXN] ;
char s[MAXN] , ss[MAXN] ;
string p[MAXQ] ;
int op[MAXQ] ;
int nxt[MAXN][26] , fail[MAXN] , idx[MAXN] , in[MAXN] , ou[MAXN] , point , root , dfs_clock ;
int c[1000] , val[MAXN] ;
int n , m ;
int Q[MAXN] , l , r ;
int newnode () {
clr ( nxt[point] , 0 ) ;
return point ++ ;
}
void init () {
point = 0 ;
root = newnode () ;
}
void insert ( string& s , int n , int id ) {
int u = root ;
for ( int i = 0 ; i < n ; ++ i ) {
int x = s[i] - 'a' ;
if ( !nxt[u][x] ) nxt[u][x] = newnode () ;
u = nxt[u][x] ;
}
idx[id] = u ;
}
void dfs ( int u ) {
in[u] = ++ dfs_clock ;
for ( int i = 0 ; i < G[u].size () ; ++ i ) dfs ( G[u][i] ) ;
ou[u] = dfs_clock ;
}
void build () {
l = r = 0 ;
fail[root] = root ;
for ( int i = 0 ; i < 26 ; ++ i ) {
if ( !nxt[root][i] ) nxt[root][i] = root ;
else {
fail[Q[r ++] = nxt[root][i]] = root ;
G[root].push_back ( nxt[root][i] ) ;
}
}
while ( l != r ) {
int u = Q[l ++] ;
for ( int i = 0 ; i < 26 ; ++ i ) {
if ( !nxt[u][i] ) nxt[u][i] = nxt[fail[u]][i] ;
else {
fail[Q[r ++] = nxt[u][i]] = nxt[fail[u]][i] ;
G[nxt[fail[u]][i]].push_back ( nxt[u][i] ) ;
}
}
}
dfs_clock = 0 ;
dfs ( root ) ;
}
inline void add ( int x , int v ) {
c[x / SQR2] += v ;
val[x] += v ;
}
int sum ( int x , int y ) {
int L = x / SQR2 + 1 ;
int R = y / SQR2 - 1 ;
int ans = 0 ;
if ( R + 1 <= L ) {
for ( int i = x ; i <= y ; ++ i ) {
ans += val[i] ;
}
} else {
for ( int i = L ; i <= R ; ++ i ) {
ans += c[i] ;
}
L *= SQR2 ;
R *= SQR2 ;
for ( int i = x ; i < L ; ++ i ) {
ans += val[i] ;
}
for ( int i = R + SQR2 ; i <= y ; ++ i ) {
ans += val[i] ;
}
}
return ans ;
}
int getpos ( char s[] , int L , int R ) {
int u = root ;
for ( int i = L ; i < R ; ++ i ) {
int x = s[i] - 'a' ;
u = nxt[u][x] ;
}
return u ;
}
void addv ( char s[] , int L , int R , int v , int now ) {
int u = now ;
for ( int i = L ; i < R ; ++ i ) {
int x = s[i] - 'a' ;
u = nxt[u][x] ;
add ( in[u] , v ) ;
}
}
void get_fail ( char p[] , int m ) {
fail[1] = 0 ;
for ( int i = 2 , j = 0 ; i <= m ; ++ i ) {
while ( j && p[i] != p[j + 1] ) j = fail[j] ;
if ( p[i] == p[j + 1] ) ++ j ;
fail[i] = j ;
}
}
int kmp ( char s[] , int n , char p[] , int m ) {
int ans = 0 ;
for ( int i = 0 , j = 0 ; i < n ; ++ i ) {
while ( j && s[i] != p[j + 1] ) j = fail[j] ;
if ( s[i] == p[j + 1] ) {
++ j ;
if ( j == m ) {
++ ans ;
j = fail[j] ;
}
} else j = fail[j] ;
}
return ans ;
}
void solve () {
init () ;
for ( int i = 0 ; i < m ; ++ i ) {
scanf ( "%d" , &op[i] ) ;
cin >> p[i] ;
if ( op[i] == 0 && p[i].length () <= SQR1 ) insert ( p[i] , p[i].length () , i ) ;
}
for ( int i = 0 ; i < point ; ++ i ) {
G[i].clear () ;
}
build () ;
clr ( c , 0 ) ;
clr ( val , 0 ) ;
addv ( s , 0 , n , 1 , root ) ;
for ( int i = 0 ; i < m ; ++ i ) {
if ( op[i] ) {
-- op[i] ;
int L = max ( 0 , op[i] - SQR1 ) , R = min ( n , op[i] + SQR1 ) ;
int now = getpos ( s , L , op[i] ) ;
addv ( s , op[i] , R , -1 , now ) ;
s[op[i]] = p[i][0] ;
addv ( s , op[i] , R , 1 , now ) ;
} else {
if ( p[i].length () > SQR1 ) {
int len = 0 ;
for ( int j = 0 ; j < p[i].length () ; ++ j ) {
ss[++ len] = p[i][j] ;
}
get_fail ( ss , len ) ;
printf ( "%d\n" , kmp ( s , n , ss , len ) ) ;
} else {
int ans = sum ( in[idx[i]] , ou[idx[i]] ) ;
printf ( "%d\n" , ans ) ;
}
}
}
}
int main () {
while ( ~scanf ( "%d%d%s" , &n , &m , s ) ) solve () ;
return 0 ;
}
xtu 1252 J题 Defense Tower
In ICPCCamp, there are n cities and (n−1) (bidirectional) roads between cities. The i-th road is between the ai-th and bi-th cities. It is guaranteed that cities are connected.
In the i-th city, there is a defense tower with power pi. The tower protects all cities with a road directly connected to city i. However, the tower in city i does not protect city i itself.
Bobo would like to destroy all defense towers. When he tries to destroy the tower in city i, any not-destroyed tower protecting city i will deal damage whose value equals to its power to Bobo.
Find out the minimum total damage Bobo will receive if he chooses the order to destroy the towers optimally.
The input contains at most 30 sets. For each set:
The first line contains an integer n (1≤n≤105).
The second line contains n integers p1,p2,…,pn (1≤pi≤104).
The i-th of the last (n−1) lines contains 2 integers ai,bi (1≤ai,bi≤n).
For each set, an integer denotes the minimum total damage.
3
1 2 3
1 2
2 3
3
1 100 1
1 2
2 3
3
2
思路:考虑每条边对玩家的伤害
假设连接的节点是u,v,破坏力是p[u]和p[v]
假设p[u]>p[v]
现在考虑u,v的删除顺序,如果先删u,这条边对玩家的伤害,是p[v],先删v,伤害是p[u]
所以显然对于每条边,我们都要先删权值大的,才能最好
怎么样才能对于每条边先删最大的呢,那就按照权值递减删就好了
所以 ret=Σ(min(p[u],p[v]))
复杂度O(n)
AC代码:
#include
#include
#include
#include
using namespace std;
const int M=100000+10;
int p[M];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
}
for(int i=1;i
---恢复内容结束---