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; }
相关文章推荐
- [PHP] 图像二次渲染
- 【iframe与父页面重合】
- 垂直搜索引擎中的分词系统
- switch case
- 在C#中使用C++编写的类1
- C#调用函数传参数IEnumerable<ClassA> classlist.ToList(),不会改变classlist
- SqlServer查询同一张表中多个字段相同的记录
- CAD控件:COM接口实现自定义实体的方法
- 第6章 C控制语句:循环
- iframe参数
- Path相关评论的方法(一)
- map结构初探
- 在onDestroy方法中做处理要小心
- iscsi网络存储
- LintCode PlusOne 加一
- 【测试实验】stm32 usart 前导符,空闲符号,断开符号
- Zookeeper 05 示例代码-主备节点切换
- html img热区坐标根据屏幕大小自适应
- 关于两幅图中相位查找的算法
- linux命令九:grep