您的位置:首页 > 其它

Codeforces #272 Div 1 简要题解

2015-06-18 15:43 274 查看

比赛总结

这次打得比上次稍微好点(其实主要是开了挂的缘故),三个题中只有A wa了一发,B和C都是fb。在正式和非正式选手中排名146名,在正式选手里排名120名

A. Dreamoon and Sums

题目链接

http://codeforces.com/contest/477/problem/A

题目大意

定义一个数字xx是优美的,当且仅当xmodb≠0,⌊xb⌋xmodb=k,k∈[1,a]x \mod b\neq 0,\frac{\lfloor \frac x b\rfloor}{x\mod b}=k,k\in [1,a],求所有优美的数字之和

思路

若xmodb=1x \mod b=1,则满足条件的xx有:

b+1b+1,2b+12b+1…ab+1ab+1

若xmodb=2x \mod b=2,则满足条件的xx有:

2(b+1)2(b+1),2(2b+1)2(2b+1)…2(ab+1)2(ab+1)

若xmodb=tx \mod b=t,则满足条件的xx有:

t(b+1)t(b+1),t(2b+1)t(2b+1)…t(ab+1)t(ab+1)

每种情况都是一个等差数列,直接对等差数列求和即可,即xmodb=tx \mod b=t,则满足条件的xx之和为(b+1+ab+1)at2\frac {(b+1+ab+1)at}2

注意乘法过程会炸掉long long int,因此要先对atat或(b+1+ab+1)(b+1+ab+1)之一除以2,然后对两个乘数分别取模后再做乘法

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MOD 1000000007

using namespace std;

typedef long long int LL;

LL sum=0;
LL a,b;

int main()
{
scanf("%I64d%I64d",&a,&b);
for(LL t=1;t<b;t++)
{
LL x=(b+1+a*b+1),y=a*t;
if(x%2==0) x/=2;
else y/=2;
x%=MOD,y%=MOD; //!!!!!
sum=(sum+(x*y%MOD))%MOD;
}
printf("%I64d\n",sum);
return 0;
}


B. Dreamoon and Sets

题目链接

http://codeforces.com/contest/477/problem/B

题目大意

要你构造nn行数字,每行4个数字,数字均互不相同,使得每行四个数字中任意两个数字的gcd恰好为kk,要你构造这些数字,并且要让最大的数字最小

思路

显然构造的数字应该是这样的格式

a1,1k,a1,2k,a1,3k,a1,4ka_{1,1}k,a_{1,2}k,a_{1,3}k,a_{1,4}k

a2,1k,a2,2k,a2,3k,a2,4ka_{2,1}k,a_{2,2}k,a_{2,3}k,a_{2,4}k

……

an,1k,an,2k,an,3k,an,4ka_{n,1}k,a_{n,2}k,a_{n,3}k,a_{n,4}k

显然每一行的四个a均互质才行,那么最简单的构造方法就是四个a均取质数,然而这样做还不是最优解。最优解下,每行四个a里,三个是质数,一个是偶数,同样能满足互质的条件。

观察样例1和2可以构造这样的答案:

1k,2k,3k,5k1k,2k,3k,5k

7k,8k,9k,11k7k,8k,9k,11k

13k,14k,15k,17k13k,14k,15k,17k

……

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

using namespace std;

typedef long long int LL;

int main()
{
LL a=1,b=2,c=3,d=5;
LL n,K;
scanf("%I64d%I64d",&n,&K);
printf("%I64d\n",K*(5+(n-1)*6));
for(LL i=1;i<=n;i++)
{
printf("%I64d %I64d %I64d %I64d\n",a*K,b*K,c*K,d*K);
a+=6,b+=6,c+=6,d+=6;
}
return 0;
}


C. Dreamoon and Strings

题目链接

http://codeforces.com/contest/477/problem/C

题目大意

给你一个字符串,问这个字符串删去1,2,3…|S||S|次后,最多能包含多少个TT串

思路

用f[i][j]f[i][j]表示SS串前ii个字符,删去jj次后最多能包含多少个TT串。在求所有f[i][]f[i][]前,我们先找出最大的pp,使得[p,i][p,i]区间删去若干字符后可以匹配上一个TT串。假设这个区间要删去tt个字符。则一些f[i][j]f[i][j]可以从f[p−1][j−t]f[p-1][j-t]转移而来,而另一些则只能从f[i−1][j]f[i-1][j]转移而来,具体看代码

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 2100

using namespace std;

typedef long long int LL;

int f[MAXN][MAXN];
char S[MAXN],T[MAXN];
int lenS,lenT;

int main()
{
scanf("%s%s",S+1,T+1);
lenS=strlen(S+1);
lenT=strlen(T+1);
for(int i=lenT;i<=lenS;i++)
{

bool flag=true;
int p1,p2;
for(p1=i,p2=lenT;p2>=1&&p1>=1;p1--)
if(S[p1]==T[p2]) p2--;
p1++; //[p1,i]段构成一个T串
if(!p2)
{
for(int j=0;j<=i;j++) //删除j次字符
if(j-(i-p1+1-lenT)>=0&&j-(i-p1+1-lenT)<=p1-1) //!!!!!!
f[i][j]=f[p1-1][j-(i-p1+1-lenT)]+1;
}
for(int j=0;j<=i-1;j++)
f[i][j]=max(f[i][j],f[i-1][j]);
}
for(int j=0;j<=lenS;j++)
printf("%d ",f[lenS][j]);
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: