链接:GZHUACM第七周
闲话:开始记录的第一场训练赛。这场两点开始,当天补课(高数课旷不得)所以迟到了两个小时,不过前四题很友好,后面的写不了,所以其实也没差。(怎么还押韵了)我要丢掉百度的坏习惯。之前训练没有思路就百度一下题目类型往某个算法或者思维想,并且时不时百度算法模板。在这里提醒下自己,不能白白浪费这么好的机会。
那么就开始吧。
原题链接:计蒜客 - T1179
题意:一个十进制数输出二进制下1的个数。
题解:很简单暴力即可,由于二进制末位与奇偶对应,所以可以不断取奇偶和右移遍历每一个二进制位。
// violet apricity
// Do all I can do.Do good to be good.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>
#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'
STD
int main()
{
IOS
ll a;
cin>>a;
ll ans=0;
while (a)
{
if(a%2==1)ans++;
a>>=1;
}
cout<<ans<<'\n';
//SYP
return 0;
}
原题链接:B - 实数加法
题意:大浮点数相加,形如:ppppppp.qqqqqqq
题解:emmm怎么说呢,大数这玩意说难不难说简单不简单,一个对新手来说考验码力和细节的东西,第一次写是快八个月前了,先后写过好几次,到现在还是不够熟悉。鸿✌说建议学手java或者存个板子,是个好主意。
// violet apricity
// Do all I can do.Do good to be good.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>
#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'
int a[1111],b[1111],len;
int main()
{
IOS
char x;
std::string s1="",s3="",s2="",s4="";
//来存下数字,注意整数部分要倒着存,因为是数组存运算时进位要方便
//相反,因为相加方向不一样,小数不需要倒着存
while(std::cin>>x&&x!='.')s1=x+s1;//存a整数部分
std::cin>>s2;//存a小数部分
while(std::cin>>x&&x!='.')s3=x+s3;//存b整数部分
std::cin>>s4;//存b小数部分
if(s1.length()<s3.length())swap(s1,s3);//先处理短的
for(int i=0;i<s3.length();i++){
//遍历短的相同部分相加
a[i]+=s1[i]+s3[i]-2*'0';
if(a[i]>=10)//进位
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
}
for(int i=s3.length();i<s1.length();i++){
//长的多出来那一部分
a[i]+=s1[i]-'0';
if(a[i]>=10)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
}
if(a[s1.length()]) len=s1.length();else len=s1.length()-1;
//最后是否进位导致边长了一位
//注意小数和整数相加的差异(方向相反)
if(s2.length()<s4.length())swap(s2,s4);
for(int i=0;i<s4.length();i++) b[i]=s2[i]+s4[i]-2*'0';
for(int i=s4.length();i<s2.length();i++) b[i]=s2[i]-'0';
for(int i=s2.length()-1;i>=0;i--){
if(i==0&&b[i]>=10)//进位到个位去了
{
a[0]++;
b[0]-=10;
}
else
if(b[i]>=10)//还没进位到个位
{
b[i-1]++;
b[i]-=10;
}
}
int i=0;
while(a[i]>=10){
//小数相加的时候进了位要再处理一次整数进位
a[i+1]++;
a[i]-=10;
i++;
}
len=std::max(len,i);//进位后改变长度
for(int j=len;j>=0;j--)std::cout<<a[j];//输出整数部分
std::cout<<'.';
int d=0;
for(int j=s2.length()-1;j>=0;j--)if(b[j]){
d=j;break;}//后往前找到非0,即去掉后导0不输出
for(i=0;i<=d;i++)std::cout<<b[i];//输出小数部分
std::cout<<'\n';//OVER
//SYP
return 0;
}
原题链接:计蒜客 - T2103
题意:用括号的方式把一个非负整数用2的幂次方和表示。
题解:这和寒假在紫书上看的括号序列相比难度低了好多(根本比不了)。可以用栈模拟一下,大概就是:
1.solve(n)对n先取个log(2)得到temp,然后对内部分情况处理:
·若temp>2:说明内部还可以再分,先输出此时的2,再solve(temp)
·若temp==1:说明刚刚好,输出2结束了
·否则输出按正常输出2(temp)
2.然后处理外部:res=n-temp,若res>0说明外部还有,则:
输出+再solve(res)处理外部部分。
// violet apricity
// Do all I can do.Do good to be good.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>
#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'
const int mod=10007;
void solve(ll n)
{
int d=2;
int cnt=0;
int temp=log(n)/log(2);
if(temp>2){
std::cout<<"2(";
solve(temp);
std::cout<<")";
}
else if(temp==1){
std::cout<<"2";
}
else {
std::cout<<2<<"("<<temp<<")";
}
int res=n-(int)std::pow(2,temp);
if(res>0){
std::cout<<"+";
solve(res);
}
}
int main()
{
IOS
ll n;
std::cin>>n;
solve(n);
std::cout<<'\n';
//SYP
return 0;
}
原题链接:计蒜客 - T1765
题意:定义了三种新运算符。输入一堆数轮流三种运算取模后输出结果。
题解:直接模拟即可。
// violet apricity
// Do all I can do.Do good to be good.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>
#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'
STD
const int mod=10007;
int main()
{
IOS
ll n;
cin>>n;
ll cnt=0;
ll ans=0;
cin>>ans;
n--;
while(n--){
ll x;cin>>x;
if(cnt==0)ans=((ans*ans%mod)+(x*x%mod))%mod;
else if(cnt==1)ans=((ans*ans%mod*ans%mod)%mod+x)%mod;
else if(cnt==2)ans=(ans+(x*x%mod*x%mod)%mod)%mod;
cnt++;
cnt%=3;
}
cout<<ans<<'\n';
//SYP
return 0;
}
到此为止前四到简单题,下面的都是有点难度的,我只会写E,还是莫名其妙过的。
原题链接:计蒜客 - 38232
题意:给出一个母串和n个子串,判断子串是否位母串的子串。
题解:可以暴力过,也可以两个数组存个位置。
师兄题解是这么说的:序列自动机,就是找每个点右边的每个字符的位置。
我还不清楚自动机,记得好像写过类似的瞎搞就过了。
我的代码:
// violet apricity
// Do all I can do.Do good to be good.
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>
#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'
const int N=111111;
int a[100];
int b[100];
std::vector<int>ans;
const int mod=10007;
char s[N],c[N];
int has[N][130];
void pre(int x,int y)
{
for(int i=0; i<130; i++)has[x][i]=has[x+1][i];
has[x][y]=x;
}
int main()
{
IOS
std::cin>>s;
int n;
std::cin>>n;
int len=strlen(s);
memset(has,-1,sizeof(has));
for(int i=len-1; i>=0; i--)
{
int x=(int)s[i];
pre(i,x);
}
while(n--)
{
std::cin>>c;
int temp=strlen(c);
int i=0,j=0;
for(j=0; j<temp; j++)
{
int x=(int)c[j];
int y=has[i][x];
if(y<i)break;
i=y+1;
}
if(j>=temp)std::cout<<"YES\n";
else std::cout<<"NO\n";
}
//SYP
return 0;
}
师兄的代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
char s[100010],t[1010];
int nxt[100010][26];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>s+1;
int n=strlen(s+1);
//建序列自动机
for(int i=0;i<26;i++) nxt[n][i]=n+1;
for(int i=n-1;i>=0;i--){
for(int j=0;j<26;j++)
nxt[i][j]=(s[i+1]=='a'+j?i+1:nxt[i+1][j]);
}
int m;
cin>>m;
while(m--){
cin>>t+1;
int len=strlen(t+1);
int i=0,j=0;
while(i<len+1){
j=nxt[j][t[i]-'a'];
if(j==n+1) break;
i++;
}
if(i==len+1) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
}
下面的暂时不会啦,留着以后补吧。
>_<
じゃ、またね