D:heilong的烦恼
题意:根据运算符决定运算,最后输出运算结果
思路:循环+数组存储
因为代码实在是太长了,我才你一定不怎么会看所以我先将核心进位代码写在这里
加法进位:
c[i]=a[i]+b[i];
if(c[i]>=10){
c[i]%=10;
c[i+1]++;
}
减法进位:
if(a[i]<b[i]){
a[i+1]--;
a[i]+=10;
}
c[i]=a[i]-b[i];
乘法进位:
c[i+j-1]=a[i]*b[j]+x+c[i+j-1];
x=c[i+j-1]/10;
c[i+j-1]%=10;
至于除法:
用减法来模拟除法,对于被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数组小于10,所以对于每一位最多进行10次运算)
好了现在我们来看看具体代码是怎么写的
加法运算:
void jiafa(){
int lena,lenb,lenc,i,j,k,x;
string s,ss;
cin>>s;
cin>>ss;
lena=s.size();
lenb=ss.size();
fe(i,0,lena-1)a[lena-i]=s[i]-'0';//这里我们要先将字符串化成数组
fe(i,0,lenb-1)b[lenb-i]=ss[i]-'0';//
lenc=1;
x=0;
while(lenc<=lena||lenc<=lenb){//直接相加,然后加的时候考虑进位
c[lenc]=a[lenc]+b[lenc]+x;
x=c[lenc]/10;
c[lenc]%=10;
lenc++;
}
c[lenc]=x;
if(c[lenc]==0)lenc--;//由于我们是直接相加,所以当两个数的长度不同的时候,我们是存在前导0的
de(i,lenc,1)cout<<c[i];
cout<<endl;
return;
}
下面是减法运算:在开始减法运算前,我们需要知道,用大数减去小数是最简单的,所以我们先判断前面的那个数是大数还是小数,如果是小数的话我们就需要先输出一个“-”。
void jianfa(){
int lena,lenb,lenc,i,j,k,x;
string s,ss;
cin>>s;
cin>>ss;
lena=s.size();
lenb=ss.size();
if(lena<lenb||(lena==lenb&&s<ss)){
swap(lena,lenb);
swap(s,ss); //由于我们的string是可以直接进行比较的所以我们没有
cout<<"-"; //必要转化了数组再去比较,直接比
}
fe(i,0,lena-1)a[lena-i]=s[i]-'0';//处理字符串
fe(i,0,lenb-1)b[lenb-i]=ss[i]-'0';
i=1;
while(i<=lena||i<=lenb){//进行减法的时候,考虑什么时候会被借位
if(a[i]<b[i]){
a[i]+=10;
a[i+1]--;
}
c[i]=a[i]-b[i];
i++;
}
lenc=i;
while(c[lenc]==0&&lenc>1)lenc--;//老规矩处理前导0
de(i,lenc,1)cout<<c[i];
cout<<endl;
return;
}
乘法运算:
void chengfa(){
int lena,lenb,lenc,i,j,k,x;
string s,ss;
cin>>s;
cin>>ss;
lena=s.size();
lenb=ss.size();
fe(i,0,lena-1)a[lena-i]=s[i]-'0';//处理字符串
fe(i,0,lenb-1)b[lenb-i]=ss[i]-'0';
fe(i,1,lena){//处理数组和进位问题
x=0;
fe(j,1,lenb){
c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//当前乘积+上次乘积进位+原数
x=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+lenb]=x; //进位
}
lenc=lena+lenb;
while(c[lenc]==0&&lenc>1)lenc--;//别忘记删除前导0
de(i,lenc,1)cout<<c[i];
cout<<endl;
return;
}
除法这几个里面较难的一个,下面我们看看把
int compare(){//比较现在的a和tmp的大小
int i;
if(a[0]>tmp[0])return 1;
if(a[0]<tmp[0])return -1;
de(i,a[0],1){
if(a[i]>tmp[i])return 1;
if(a[i]<tmp[i])return -1;
}
return 0;
}
void jian(){
int flag,i;
flag=compare();
if(!flag){
a[0]=0;
return ;
}
if(flag==1){
fe(i,1,a[0]){
if(a[i]<tmp[i]){
a[i+1]--;
a[i]+=10;
}
a[i]-=tmp[i];
}
while(a[0]>0&&a[a[0]]==0)a[0]--;
return;
}
}
void chufa(){
int lena,lenb,lenc,i,j,k,x;
string s,ss;
cin>>s;
cin>>ss;
a[0]=s.size();
b[0]=ss.size();
if(s.size()<ss.size()||(s.size()==ss.size()&&s<ss)){
cout<<0<<endl<<s<<endl;
return;
}
fe(i,1,a[0])a[i]=s[a[0]-i]-'0';
fe(i,1,b[0])b[i]=ss[b[0]-i]-'0';
c[0]=a[0]-b[0]+1;
de(i,c[0],1){
memset(tmp,0,sizeof(tmp));
fe(j,1,b[0])tmp[j+i-1]=b[j];
tmp[0]=b[0]+i-1;
while(compare()>=0){//减法模拟,都是a数组与tmp的比较
c[i]++;
jian();
}
}
while(c[0]>0&&c[c[0]]==0)c[0]--;
if(c[0]==0){
cout<<0<<endl;
}else{
de(i,c[0],1)cout<<c[i];//c是最后的商
cout<<endl;
}
if(a[0]==0){
cout<<0<<endl;
}else{
de(i,a[0],1)cout<<a[i];//a是最后的余数
cout<<endl;
}
return ;
}
E:凢凢的烦恼
题意:给你两个数,a和b,求(a!)%(M),(b!)%(M),M=97126719690。
思路:我们这里有两种思路,首先我们看到这道题的数据之大,我们就可以猜测这道题必定不会是暴力可以做到的,但是我们又发现这题这么简单,会不会是我们想复杂了呢?特别是这种我们一看输出特定值的题,一般情况都会是有规律的(除非出题人是狗)那么我们就先暴力暴力
int x,y;int da1=1,da2=1;
while(1){
cin>>x;
for(i=1;i<=x;i++){
da1*=i;
da1%=M;
}
cout<<da1<<endl;
}
然后我们就会发现,到达某个值后,后面的da1全为0,这个时候我们仔细找找就会发现那个值为1033
这道题的答案也就呼之欲出啦(是不是很简单啦(๑•̀ㅂ•́)و✧)
int i,j;
int x,y;int da1=1,da2=1;
cin>>x>>y;
if(x>1033)da1=0;
else{
for(i=1;i<=x;i++){
da1*=i;
da1%=pi;
}
}
if(y>1033)da2=0;
else{
for(i=1;i<=y;i++){
da2*=i;
da2%=pi;
}
}
if(da1>da2)cout<<"@@"<<endl;
else if(da1<da2)cout<<"heilong"<<endl;
else cout<<"kewu"<<endl;
我的天哪我们这么快就写到了F题了吗?w(゚Д゚)w
F:圈圈的烦恼
题意:这道题嘛,咱们抽象抽象,最后就可以看成在一段序列中,找到最长上升子序列,只不过呢,因为这次的数据比较大,我们不可能再用原来()的办法了,5e5的数据必定会TLE的,因此我们需要想一想如何将时间复杂度压缩到(n)到(nlogn)不然就要凉凉︿( ̄︶ ̄)︿
思路:那么应该是跑一遍就应该要出答案,首先明确一个点,我们要知道,要想上升子序列最长,那么每一跳的高度要尽可能的低。
此时我们创建一个dp[len]数组
len是现在我们得到的最长上升子序列的长度
然后就是不断的去维护这个dp数组了。
当前a[i]>dp[len]时,说明这个a[i]满足条件,那么我们这时更新数组,dp[++len]=a[i]
不然,我们就在dp数组中找到一个dp[j],使得a[i]<dp[j]<=a[i+1],此时我们更新数组dp[j]=a[i+1]
第一步我相信大家应该都理解了,我们来看第二步,首先现在的最长子序列的长度是已经确定了的,必定长为len,那么这个时候,如果能够找到这一个j,更新dp数组,使得dp数组一直保持着线性的性质,方便我们查找,这个时候你会问,那我更改dp[len]值怎么办,那我们既然能够使得我dp[len]>a[i],那么我就是满足最长上升子序列的性质,那么就可以更改,这又有什么关系呢?
举个例子┗|`O′|┛ 嗷~~
1 3 8 5 7
我们发现8能够在3后面,5也能在3后面,那为什么我们不让5在3的后面呢?
那么现在我们来瞅瞅代码:
cin>>n;
fe(i,1,n)cin>>a[i];
len=1;dp[len]=a[1];
fe(i,2,n){
if(a[i]>dp[len])dp[++len]=a[i];
else {
da1=lb(dp+1,dp+len+1,a[i])-dp;//二分查找,减少时间复杂度,阔以自己写二分哦
dp[da1]=a[i]; //我用的自带的二分
}
}
cout<<len<<endl;
是不是很吃惊,是不是感觉很惊讶o(*^@^*)o,没办法有些题,想到了就很简单,想不到它也很简单,只不过做不来而已~~( ﹁ ﹁ ) ~~~
好吧今天的题解就到这里,期待下一次的相遇(づ ̄3 ̄)づ╭❤~