两个一血,舒服
----------------------------------------------------
A
模拟题,给出n个固定位置的值,然后给出目标位置值,每个固定位置只能向前走,求最小消耗
很简单,就是累和每个数与他左边最近的固定数的距离
我看数据范围不大,直接暴力打表了。。
int n;
string str[maxn];
string cup[96]={
"A1","A1#","B1","C1","C1#","D1","D1#","E1","F1","F1#","G1","G1#",
"A2","A2#","B2","C2","C2#","D2","D2#","E2","F2","F2#","G2","G2#",
"A3","A3#","B3","C3","C3#","D3","D3#","E3","F3","F3#","G3","G3#"
,"A4","A4#","B4","C4","C4#","D4","D4#","E4","F4","F4#","G4","G4#"
,"A5","A5#","B5","C5","C5#","D5","D5#","E5","F5","F5#","G5","G5#"
,"A6","A6#","B6","C6","C6#","D6","D6#","E6","F6","F6#","G6","G6#"
,"A7","A7#","B7","C7","C7#","D7","D7#","E7","F7","F7#","G7","G7#"
,"A8","A8#","B1","C8","C8#","D8","D8#","E8","F8","F8#","G8","G8#"};
bool judge(string str){
if(str=="F1#"||str=="F2#"||str=="F3#"||str=="F4#"||str=="F5#"){
return true;
}else{
return false;
}
}
int seek(string str){
int ed,st;
rep(i,0,95){
if(cup[i]==str){
ed=i;
// de(ed)
per(j,i,0){
if(judge(cup[j])){
return i-j;
}
}
}
}
}
int check(string str){
rep(i,0,95){
if(cup[i]==str){
return i-1;
}
}
}
string change(string str){
int sz=str.size();
if(str[sz-1]=='b'){
int num=str[1]-'A'+1;
char ch=str[0];
string c;
c+=str[0];
c+=str[1];
int pos=check(c);
c=cup[pos];
return c;
}else{
return str;
}
}
void solve(){
int ans = 0;
cin>>n;
rep(i,1,n){
cin>>str[i];
str[i]=change(str[i]);
//de(str[i])
int dis=seek(str[i]);
ans+=dis;
}
printf("%d\n",ans);
}
C
签到题,给出分裂方式,找出最初的形式
分裂方式很清楚了,所以我们只需要开两个
代表上下,奇数加上面,偶数加下面,然后依次输出就好了
void solve(){
string str;
cin>>str;
int sz = str.size();
string a="",b="";
rep(i,0,sz-1){
if(i%2==0){
a+=str[i];
}else{
b+=str[i];
}
}
cout<<a<<b<<endl;
}
D
第一眼,哇…数论题,溜了溜了
后来看过了好多人…心想怎么这么多数学选手啊…就会去看了看
然后就发现了精度问题…下面是指数函数,指数爆炸…精度大于
就可以了,那就很简单了,很明显这个式子的值最后的变化范围很小很小,所以超过一定范围后保留
,就相当于i相同的数了,我没算具体大概有多大会趋于一致,直接打了个
的表,交了
对于大于1e6的数,答案在保留9位小数时肯定会等于1e6的
double ans[maxn];
double arr[maxn];
void solve(){
int n =read();
n=min(n,1000000);
printf("%.10f\n",ans[n]);
}
int main(){
arr[1]=1.0/2;
arr[2]=1.0/4;
ans[0]=0;
for(int i=3;i<=1e6;i++){
arr[i]=arr[i-2]*1.0/4+arr[i-1]*1.0/2;
}
for(int i=1;i<=1e6;i++){
ans[i]=ans[i-1]+arr[i];
}
int test = 1;
//test = read();
//cin>>test;
while(test--){
solve();
}
#ifdef _LOCALE_DEBUG_PAUSE
system("pause");
#endif //_LOCALE_DEBUGE_PAUSE
return 0;
}
F
这个题我吐了,从wa到T到mle…
wa的原因是憨批了…错误思路就不说了
最小数目 很明显就是1,输出他自己
最大数目
要求
,或运算后结果为这个数,那么根据或运算的特点,一真即真,
那么方案数就应该从二进制角度下手,找出目的数在二进制下哪些位数为0,那么组成方案的数就不能含有这个位置为1的数
题目说数目不会大于1e6,算一下1e6二进制下有20位,瞎暴力差不多
先存下目标数二进制的表示,然后枚举二进制,找出所有或运算后不会破坏的数,放入set就可以了,,然后T了
正解应该是 :
找出这个数二进制下的位数
,然后先特判放入数组一个0,之后,我们从低位到高位枚举这个数二进制的表示,如果为1,那么我们就选这个数对应的2的幂,加上前面所有比它小的数,并放入数组就可以了
int y;
int ans[maxn];
void solve(){
y = read();
puts("1");
printf("%d\n",y);
if(y==0){
printf("1\n0\n");
return ;
}
int tmp = y;
int base = 1;
int cnt = 0;
int len = 0;
ans[++len]=0;
while(tmp){
base = (1<<cnt);
if(tmp&1){
int ed=len;
rep(i,1,len){
ans[++ed]=base+ans[i];
}
len=ed;
}
cnt++;
tmp>>=1;
}
printf("%d\n",len);
rep(i,1,len){
printf("%d\n",ans[i]);
}
}
L
看题目有意思就点了,然后开到一个签到题,笑死我了
抢了个一血
这个没啥好说的,就是一个取模
void solve(){
int x = read(),n = read();
int ans = (x+n-1)%7+1;
printf("%d\n",ans);
}
M
最长上升子序列板子题
我拿一血啦
区别在于输出路径且要求字典序最大,关于记录路径问题
我们只需要多加一个标记,记录一下,当前位置产生的最长长度,然后倒着推len,len-1,len-2…1就好了
ll arr[maxn],cup[maxn],dp[maxn],vis[maxn];
ll p,n;
void solve(){
n = read(), p = read();
rep(i,1,n){
vis[i] = 0;
arr[i] = read();
dp[i] = 0;
}
ll len = 0;
rep(i,1,n){
if(len == 0 || arr[i] > cup[len]){
cup[++len] = arr[i];
dp[i] = len;
}else{
int pos = lower_bound(cup+1,cup+len+1,arr[i])-cup;
cup[pos] = arr[i];
dp[i] = pos;
}
}
ll tmp = len;
ll ans = 0;
per(i,n,1){
if(dp[i]==tmp){
tmp--;
vis[i]=1;
ans+=arr[i];
}
}
cout<<ans+p<<endl;
cout<<len<<endl;
rep(i,1,n){
if(vis[i]){
cout<<i<<endl;
}
}
}