考试心得
对于今天考试的时候,长进最大的就是自己没有睡觉,没有跑神;
虽然今天考的不是很好,但是自己的期望得分和实际得分是吻合的,所以自己觉得可以拿到的暴力分都拿到手了。所以今天对自己的表现还算满意。
只要目标向前,你可以到任何的地方。
需要长进的地方:自己以后拿到一份题的时候,可以先看一眼数据范围,之后再开始算自己可以拿到的部分分。
正文部分
第一题
1.PCR
(pcr.pas/c/cpp)
【背景】
PCR(多聚酶链式反应)技术是一种机器自动控制的人工dna复制技术。
【问题描述】
该技术中根据生成dna两条链的长度可以将生成的dna分成长中、中短、短短三种类型。
由图示可以看出,第一次循环的时候模板链会产生两条长中型dna,从第二次循环开始,每条长中型dna可以生成长中和中短型dna各一条,每条中短型dna可以生成中短和短短型dna各一条,而每条短短型dna可以生成两条短短型dna。
在pcr生成的所有dna产物中,只有短短型dna是我们需要的目的基因,现在问你,pcr技术进行n次循环后会产生多少目的基因?
因为答案可能很大,你只需要输出目的基因数%19260817的结果
【输入】
一行一个整数n
【输出】
一行一个整数表示目的基因数对大整数取模的结果
【输入输出样例1】
pcr.in pcr.out
4 8
【数据范围】
有10%的数据:n=2
有10%的数据:n=3
有10%的数据:n=5
对于50%的数据:n<=10^6
对于100%的数据:n<=10^18
题解
所以,我就拿到了50分。。。。。
code
#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <list>
#include <map>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
const int MOD=19260817;
typedef long long ll;
ll n;
inline ll read()
{
ll x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
ll power(ll a,ll b)/*a^b*/
{
ll sum=1;
while(b)
{
if(b&1) sum=(sum*a)%MOD;
a=(a*a)%MOD;
b=b>>1;
}
return sum%MOD;
}
int main()
{
freopen("pcr.in","r",stdin);
freopen("pcr.out","w",stdout);
n=read();
ll ans=power(2,n);
ans=(ans-2*n)%MOD;
if(ans<0) ans+=MOD;
printf("%lld\n",ans);
return 0;
}
第二题
2.排列
(arrange.pas/c/cpp)
【背景】
排列组合是高考数学中常见的套路题,而且往往属于大家都会做但是却又做不对的毒瘤题。
图为19年一卷理数15题。
【问题描述】
现在你又被毒瘤高考出题人恶心到了,打算写个cpp教他什么叫排列组合。
给你一个数字串s和一个整数d,统计s有多少种不同的排列(允许前导0)能被d整除。例如114514有20种排列能被2整除。
【输入】
第一行是一个整数T,表示测试数据的个数,接下来T行每行一组用空格隔开的s和d。s保证只含数字0到9
【输出】
共T行,含义如题
【输入输出样例1】
arrange.in arrange.out
7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29 1
3
3628800
90
3
6
1398
【数据范围】
对于20%的数据:s的长度不超过5
对于50%的数据:s的长度不超过8
对于100%的数据:s的长度不超过10,1<=d<=1000,1<=T<=15
题解
code
还有一种懒方法就是next_permutation()。
这里就要简单介绍一下什么是next_permutation():
按照我的理解就是可以把一个数组进行全排列的操作,而且会自动去掉重复出现的序列(因为可能有的数字是会重复出现的,就比如说是:1,1,2,3)
我们输出一下STL之后的操作:
int main()
{
int a[10]={1,1,2,3};
do{
for(int i=0;i<4;++i)
cout<<a[i]<<' ';
cout<<endl;
}while(next_permutation(a,a+4));
return 0;
}
对于上面的结果,我们可以清楚地发现:
-
从整体来看,每一个排列顺序都是递增的,所以这个时候要找出来所有的全排列出来就要求我们对于要排列的序列进行升序处理。
-
而且对于有重复数字出现的情况,并不会出现重复的序列,所以该STL实际上还是可以判重的。
之后就是代码的处理:
#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <list>
#include <map>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
int t,d,cnt;
int h[20];
ll ans=0;
int main()
{
freopen("arrange.in", "r", stdin);
freopen("arrange.out", "w", stdout);
scanf("%d",&t);
while(t--)
{
string a;
cin>>a; cnt=a.size(); ans=0ll;
scanf("%d",&d);
memset(h,0,sizeof(h));
for(int i=1;i<=a.size();++i)
h[i]=a[i-1]-'0';
sort(h+1,h+1+cnt);/*升序排列*/
do{
ll sum=0;/*注意:a序列中有10位数字,所以这里要开ll*/
for(int i=1;i<=cnt;++i)
sum=sum*10+h[i];
if(sum%d==0) ans++;
}while(next_permutation(h+1,h+1+cnt));/*当返回0的时候就已经没有变化的序列了,也就是说已经变成了降序的序列*/
printf("%lld\n",ans);
}
return 0;
}
注意:
- 食用之前一定要记得升序处理;
- 对于某些数字一定要开 ll 的操作。
要成功,先发疯,头脑简单向前冲。