这次打得比上次稍微好点(其实主要是开了挂的缘故),三个题中只有A wa了一发,B和C都是fb。在正式和非正式选手中排名146名,在正式选手里排名120名
http://codeforces.com/contest/477/problem/A
定义一个数字 x 是优美的,当且仅当 xmodb≠0,⌊xb⌋xmodb=k,k∈[1,a] ,求所有优美的数字之和
若 xmodb=1 ,则满足条件的 x 有:
b+1 , 2b+1 … ab+1
若 xmodb=2 ,则满足条件的 x 有:
2(b+1) , 2(2b+1) … 2(ab+1)
若 xmodb=t ,则满足条件的 x 有:
t(b+1) , t(2b+1) … t(ab+1)
每种情况都是一个等差数列,直接对等差数列求和即可,即 xmodb=t ,则满足条件的 x 之和为 (b+1+ab+1)at2
注意乘法过程会炸掉long long int,因此要先对 at 或 (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;
}
http://codeforces.com/contest/477/problem/B
要你构造 n 行数字,每行4个数字,数字均互不相同,使得每行四个数字中任意两个数字的gcd恰好为 k ,要你构造这些数字,并且要让最大的数字最小
显然构造的数字应该是这样的格式
a1,1k,a1,2k,a1,3k,a1,4k
a2,1k,a2,2k,a2,3k,a2,4k
……
an,1k,an,2k,an,3k,an,4k
显然每一行的四个a均互质才行,那么最简单的构造方法就是四个a均取质数,然而这样做还不是最优解。最优解下,每行四个a里,三个是质数,一个是偶数,同样能满足互质的条件。
观察样例1和2可以构造这样的答案:
1k,2k,3k,5k
7k,8k,9k,11k
13k,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;
}
http://codeforces.com/contest/477/problem/C
给你一个字符串,问这个字符串删去1,2,3… |S| 次后,最多能包含多少个 T 串
用 f[i][j] 表示 S 串前 i 个字符,删去 j 次后最多能包含多少个 T 串。在求所有 f[i][] 前,我们先找出最大的 p ,使得 [p,i] 区间删去若干字符后可以匹配上一个 T 串。假设这个区间要删去 t 个字符。则一些 f[i][j] 可以从 f[p−1][j−t] 转移而来,而另一些则只能从 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;
}