HFOI2017.9.12 复习赛01题解
来源:互联网 发布:js modal点击旁边关闭 编辑:程序博客网 时间:2024/06/07 06:12
01:质数的和与积
- 描述
两个质数的和是S,它们的积最大是多少?
- 输入
- 一个不大于10000的正整数S,为两个质数的和。
- 输出
- 一个整数,为两个质数的最大乘积。数据保证有解。
- 样例输入
50
- 样例输出
589
- 来源
《奥数典型题举一反三(小学五年级)》 (ISBN 978-7-5445-2882-5) 第三章 第二讲 例1
这是一道小学数学题啊。。。
我的方法是先用线性筛素数打出一个素数表,然后就i从S/2开始,往下减少,如果i和(S-i)都是质数,那么输出他们的积,并且return 0;
代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;bool tf[10010]={true,true};//素数表int s;int main(){for(int i=2;i<=100;i++)//线性筛素数,对于i<=sqrt(maxn),将i的每个倍数标记为合数{if(tf[i])continue;//如果i已经是合数,那么他的倍数肯定已经被标记过了,所以无需再次标记for(int j=2;i*j<=10000;j++)tf[i*j]=true;//如果是质数,进行标记操作}scanf("%d",&s);for(int i=s/2;i>=2;i--)if(!tf[i]&&!tf[s-i])//如果i和(s-i)都是质数{printf("%d\n",i*(s-i));return 0;//输出并返回}}
02:大整数乘法
- 描述
求两个不超过200位的非负整数的积。
- 输入
- 有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
- 输出
- 一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
- 样例输入
1234567890098765432100
- 样例输出
1219326311126352690000
- 来源
- 程序设计实习2007
这题的数据有点水,不用FFT都可以过。。。但是我不会FFT
我写的代码是偏向于模板类型的(中了一点面向对象的毒),用了重载运算符
高精度的中心思想是通过类似于笔算的方法。比如说我们要计算200位+200位的加法,我们是从最低位(个位)开始,一步一步往上加,同时保存进位。
为了阅读和编写的方便,我没有用高精压位:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=410;struct bigint{int l,num[maxn];//l是大整数的长度,num保存每一位,num[0]是个位,依此类推bigint(){l=1;memset(num,0,sizeof num);}//初始化void in(){char s[maxn];scanf("%s",s);l=strlen(s);for(int i=0;i<l;i++)num[i]=s[l-i-1]-'0';}//输入函数void out(){for(int i=l-1;i>=0;i--)printf("%d",num[i]);printf("\n");}//输出函数,内置bigint operator+(bigint a)//加法操作{bigint ans;ans.l=max(l,a.l)+1;//更新长度for(int i=0;i<ans.l;i++)ans.num[i]=num[i]+a.num[i];//计算每一位的值for(int i=1;i<ans.l;i++)ans.num[i]+=ans.num[i-1]/10,ans.num[i-1]%=10;//计算进位if(!ans.num[ans.l-1])ans.l--;//判断最高位是否是0return ans;//返回}bigint move(int a)//移位操作,move(a)代表*(10^a){bigint ans;ans.l=l+a;for(int i=0;i<l;i++)ans.num[i+a]=num[i];return ans;}bigint operator*(int a)//乘法操作,乘以一个小于10的数{bigint ans;ans.l=l+1;for(int i=0;i<ans.l;i++)ans.num[i]=num[i]*a;//计算for(int i=1;i<ans.l;i++)ans.num[i]+=ans.num[i-1]/10,ans.num[i-1]%=10;//进位if(!ans.num[ans.l-1])ans.l--;//判断最高位是否为0return ans;//返回}bigint operator*(bigint a)//乘法,乘以一个大整数{bigint ans;ans.l=l+a.l+1;//更新长度for(int i=0;i<l;i++)ans=ans+(a*num[i]).move(i);//对于每一位,加上乘以这一位的值while(ans.l!=1&&!ans.num[ans.l-1])ans.l--;//判断是否需要更新总长度return ans;//返回}}a,b;int main(){a.in();b.in();//输入(a*b).out();//输出return 0;}
03:字符环
- 描述
有两个由字符构成的环。请写一个程序,计算这两个字符环上最长连续公共字符串的长度。例如,字符串“ABCEFAGADEGKABUVKLM”的首尾连在一起,构成一个环;字符串“MADJKLUVKL”的首尾连在一起,构成一个另一个环;“UVKLMA”是这两个环的一个连续公共字符串。
- 输入
- 一行,包含两个字符串,分别对应一个字符环。这两个字符串之间用单个空格分开。字符串长度不超过255,且不包含空格等空白符。
- 输出
- 输出一个整数,表示这两个字符环上最长公共字符串的长度。
- 样例输入
ABCEFAGADEGKABUVKLM MADJKLUVKL
- 样例输出
6
用DP方法求两个字符串的最长连续公共字符串的长度的方法描述如下:定义f[i][j]表示以字符串1的第i位和字符串2的第j位为结尾的最长连续公共字符串的长度,可以得出状态转移方程为:f[i][j]=(s1[i]==s2[j]?f[i-1][j-1]+1:0)
求环上的最长连续公共字符串,使用倍增的思想,把两个字符串翻倍,例如AB翻倍为ABA,ABBCCCD翻倍为ABBCCCDABBCCC,然后再求最长连续公共字符串的长度。
注意:现在得出的答案还不是正确的答案,因为这样的做法可能会把一个元素使用两次。可以证明,如果存在着一个长度为n+1的最长连续公共字符串,那么一定存在一个长度为n的最长连续公共字符串,所以最后的答案就要输出min(ans,min(l1,l2))
复杂度分析:时间复杂度O(NM),空间复杂度O(NM),通过滚动数组法可以优化到O(min(N,M))(N,M是两个字符串的长度)
代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=610;char s1[maxn],s2[maxn];int l1,l2,L1,L2,f[maxn][maxn],ans=0;int main(){memset(f,0,sizeof f);scanf("%s%s",s1,s2);l1=strlen(s1);l2=strlen(s2);for(int i=0;i<l1-1;i++)s1[i+l1]=s1[i];for(int i=0;i<l2-1;i++)s2[i+l2]=s2[i];L1=l1*2-1;L2=l2*2-1;for(int i=0;i<L1;i++)for(int j=0;j<L2;j++)if(s1[i]==s2[j])f[i+1][j+1]=f[i][j]+1,ans=max(ans,f[i+1][j+1]);printf("%d\n",min(ans,min(l1,l2)));return 0;}
- HFOI2017.9.12 复习赛01题解
- HFOI2017.9.14 复习赛02题解
- HFOI2017.07.09校内赛(普及组)题解
- HFOI2017.07.10校内赛(普及组)题解
- HFOI2017.07.11校内赛(普及组)题解
- HFOI2017.07.11校内赛(普及组)题解
- HFOI2017.7.13校内赛(普及组)题解
- HFOI2017.7.14校内赛(普及组)题解
- HFOI2017.7.15校内赛(普及组)题解
- XJOI一句话复习题解
- 资源分享:HFOI2017暑假校内赛STD 2017.7.9-2017.7.15
- 【复习+整理】【题解】noip集训考试1
- splay专题复习——bzoj 3224 & 1862 & 1503 题解
- 数位DP入门 BZOJ 1833 题解(需要复习)
- 【AcJoy群赛题解】 群赛01
- 第八周周赛——复习题解(出自codeforces 633A,610A,poj2155,poj3070,codeforces 538B,codeforces 513A)
- 【题解】2016.5.8SWJTU校赛题解
- Java 基础复习 01
- CDH5.7.2离线部署笔记
- Asp.net+Vue2构建简单记账WebApp之三(使用Vue-cli构建vue.js应用)
- 十,显示转换和隐式转换
- 泛型的高级用法
- JAVA学习之路-简单的登录界面
- HFOI2017.9.12 复习赛01题解
- 配置 iReport JDK
- JVM_垃圾收集器
- C++多态的复习
- Codeforces Round #383 (Div. 2) B, C, D
- Glide使用出现的常见问题
- DPM
- 深入分析Java中的length和length()
- Flexible实现手淘H5页面的rem布局适配