Problem A
题目描述:
按1,11,111,1111,2,22,222,2222…9999的规律依次查询,查找到x为止,求这时一共按了多少下
题目解析:
哪怕打表都能过,略
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin>>t;
while(t--){
int x;
cin>>x;
int tmp = 1;
int ans =(x%10-1)*10;
while(x){
ans += tmp++;
x /= 10;
}
cout<<ans<<endl;
}
re 0;
}
Problem B
题目描述:
把书架上零散的书移动到一起,每次选择一堆书向左/向右移1格,求最少移动次数
题目解析:
显然答案是最左侧书与最右侧书之间空格的个数。。
规定向外交换指 操作后空格在[最左侧书,最右侧书]区间以外,反之为向内交换。从最外层开始,将内部的空格向外交换,到最外层以外,与其他书合并,不断重复直至区间内没有空格。如果向内交换则导致空格被重复操作,增加次数。
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
const int MAXN = 55;
int t,n;
int store[MAXN];
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>t;
while(t--){
cin>>n;
rep(i,0,n)
cin>>store[i];
int ans = 0;
int star = 0,finish = n-1;
while(!store[star]) star ++;
while(!store[finish]) finish --;
rep(i,star,finish+1)
ans += store[i]==0;
cout<<ans<<endl;
}
re 0;
}
Problem C
题目描述:
有
n
n
n条鱼,每第
i
i
i条鱼的大小为
n
i
n_i
ni。每条鱼可以吃掉严格小于自己的鱼,问哪条鱼可以把其他鱼都吃掉
题目解析:
这个题只要给出一种可能的情况即可,不需要太复杂的考虑。当且仅当所有鱼的大小相同时,没有结果,输出-1;否则必然存在答案。
现在构造如下方案:找出所有鱼中最大的大小
m
a
x
max
max。在所有大小为
m
a
x
max
max的鱼中找到满足条件
a
i
−
1
<
a
i
∣
∣
a
i
>
a
i
+
1
a_{i-1}<a_{i} || a_i > a_{i+1}
ai−1<ai∣∣ai>ai+1的位置
i
i
i。显然,这一位置上的鱼必然存在方案吃掉所有鱼。
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
const int MAXN = 3e5+5;
int t,n;
int store[MAXN];
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>t;
while(t--){
cin>>n;
int maxNum = -1,pos = -1;
rep(i,1,n+1){
cin>>store[i];
maxNum = max(store[i],maxNum);
}
store[0] = store[n+1] = maxNum;
rep(i,1,n+1){
if(store[i]==maxNum && (store[i-1]!=maxNum || store[i+1]!=maxNum)){
pos = i;
break;
}
}
cout<<pos<<endl;
}
re 0;
}
Problem D
题目描述:
为n个城市连接道路,每个城市分别属于一个帮派。如果同隶属于相同帮派的城市相连就会出问题。求n个城市的连接方式
题目解析:
显然,如果所有城市都隶属于同一帮派,必然不可能连通。
如果有两个及以上的帮派,构造如下的连接方式
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
const int MAXN = 5005;
int t,n;
int node[MAXN];
queue<int> Q;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>t;
while(t--){
cin>>n;
rep(i,0,n){
cin>>node[i];
}
bool canMake = false;
rep(i,1,n){
if(node[i]!=node[i-1]){
canMake = true;
break;
}
}
if(canMake){
cout<<"YES"<<endl;
int kind = node[0],pos=2;
rep(i,1,n){
if(kind==node[i]){
Q.push(i+1);
}else{
pos = i+1;
cout<<"1 "<<i+1<<endl;
}
}
while(!Q.empty()){
cout<<Q.front()<<' '<<pos<<endl;
Q.pop();
}
}else{
cout<<"NO"<<endl;
}
}
re 0;
}
Problem E
题目描述:
有n个人,分成2队,求不同种分法。可以通过循环移位得到的序列被认为是相同序列。
题目解析:
我惊叹于我的奇妙智商
n=6为例
序列[1 2 3 4 5 6]共有 3X3X2 种不同记法,此序列对应一种分组方法。因而不难类推得,人数为n时,分法有
n
!
n
2
⋅
n
2
⋅
2
\frac{n!}{\frac n2 \cdot \frac n2 \cdot 2}
2n⋅2n⋅2n!种。
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>n;
ll ans = 1;
rep(i,1,n+1)
ans = 1LL * ans * i;
cout<<(ans/2/(n/2)/(n/2))<<endl;
re 0;
}
Problem F
题目描述:
给出nXm矩阵,每行选择不超过
m
2
\frac m2
2m个,求能被k整除的最大和
题目解析:
数据量不大,所以直接dp就可以了。
记
d
p
[
i
]
[
c
n
t
]
[
r
e
n
]
dp[i][cnt][ren]
dp[i][cnt][ren]第
i
i
i行选择了
c
n
t
cnt
cnt个元素和余数为
r
e
n
ren
ren的最大值。
初值
d
p
[
0
]
[
0
]
[
0
]
=
0
dp[0][0][0] = 0
dp[0][0][0]=0
递推式
d
p
[
i
]
[
c
n
t
+
1
]
[
(
r
e
n
+
a
i
j
)
%
k
]
=
m
a
x
(
d
p
[
i
]
[
c
n
t
+
1
]
[
(
r
e
n
+
a
i
j
)
%
k
]
,
d
p
[
i
]
[
c
n
t
]
[
r
e
n
]
+
a
i
j
)
dp[i][cnt+1][(ren+a_{ij})\% k ] = max( dp[i][cnt+1][(ren+a_{ij})\% k ] , dp[i][cnt][ren] + a_{ij})
dp[i][cnt+1][(ren+aij)%k]=max(dp[i][cnt+1][(ren+aij)%k],dp[i][cnt][ren]+aij)
此外将计算结果更新到下一行的初始状态中
d
p
[
i
+
1
]
[
0
]
[
r
e
n
]
=
m
a
x
(
d
p
[
i
+
1
]
[
0
]
[
r
e
n
]
,
d
p
[
i
]
[
c
n
t
]
[
r
e
n
]
)
dp[i+1][0][ren] = max(dp[i+1][0][ren],dp[i][cnt][ren])
dp[i+1][0][ren]=max(dp[i+1][0][ren],dp[i][cnt][ren])
最后
d
p
[
n
]
[
0
]
[
0
]
dp[n][0][0]
dp[n][0][0]即为结果
注意在遍历 c n t cnt cnt时需要倒序遍历,否则导致同一元素的多次选择
#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
template<class T> void _deb(const char *name,T val){
cout<<name<<val<<endl;
}
const int MAXN = 75;
int n,m,k;
int store[MAXN][MAXN];
int dp[MAXN][MAXN][MAXN];
void show();
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>n>>m>>k;
rep(i,0,n)
rep(j,0,m)
cin>>store[i][j];
rep(i,0,n+1)
rep(cnt,0,m/2+1)
rep(ren,0,k)
dp[i][cnt][ren] = -1;
dp[0][0][0] = 0;
rep(i,0,n){
rep(j,0,m){
drep(cnt,min(j+1,m/2)-1,0)
rep(ren,0,k){
if(dp[i][cnt][ren]<0)
continue;
dp[i][cnt+1][(ren+store[i][j])%k] = max(dp[i][cnt+1][(ren+store[i][j])%k],dp[i][cnt][ren]+store[i][j]);
}
}
rep(cnt,0,m/2+1)
rep(ren,0,k)
dp[i+1][0][ren] = max(dp[i+1][0][ren],dp[i][cnt][ren]);
}
cout<<max(0,dp[n][0][0])<<endl;
re 0;
}
}