Many Formulas
给了你一个字符串,你可以在任意两个字符间插入加号,而且也可以插入任意个,问你这些所有可能的算式的结果加和是多少。
那我们可以来看一下,这个字符串长度很小,我们可以举例出所有可能产生的数,记录下这个数的大小,这个数产生的位置,这个数的数位长度。对于每一个数字,我们都可以算出它可能被加和几次。每一个数面临的情况如下:——数——,枚举一下这个数之前——的位数为1,2,3,4的情况,会发现当为1时,无法插入,为0次,2时为不插和插入1个,为2次,3时为4次,4时为8次,可以看出这就是2的(n-1)次方个,后面——位数的算法与前面一致。两者在和本数去相乘。我们就可以算了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>
void solve() {
string s;
cin>>s;
int n=s.size();
int sum=0;
vector<pair<int,pair<int,int>>>a;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
int z=0;
for(int k=j;k<=j+i and j+i<n;k++){
z=z*10+(s[k]-'0');
}
if(z!=0){
a.push_back({z,{i+1,j}});
}
}
}
for(int i=0;i<a.size();i++){
int n1=a[i].second.second;
int n2=n-a[i].second.first-a[i].second.second;
if(n1>0){
n1--;
}if(n2>0){
n2--;
}
sum+=a[i].first*pow(2,n1)*pow(2,n2);
}
cout<<sum<<endl;
}
signed main() {
ios::sync_with_stdio ( false );
cin.tie ( nullptr );
cout.tie ( nullptr );
int oyyo = 1;
//cin >> oyyo;
while ( oyyo-- ) {
solve();
}
return 0;
}
Wall
😭。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>
int a[205][205];
int c[15][15];
void solve() {
int n,m;
cin>>n>>m;
int k=1;
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
cin>>c[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]!=1 and a[i][j]!=-1){
k=0;
}
}
}
if(k==1){
cout<<0<<endl;return;
}
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++){
for(int z=0;z<=9;z++){
c[j][z]=min(c[j][i]+c[i][z],c[j][z]);
}
}
}
int sum=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]!=1 and a[i][j]!=-1){
sum+=c[a[i][j]][1];
}
}
}
cout<<sum<<endl;
}
signed main() {
ios::sync_with_stdio ( false );
cin.tie ( nullptr );
cout.tie ( nullptr );
int oyyo = 1;
//cin >> oyyo;
while ( oyyo-- ) {
solve();
}
return 0;
}
Tak and Cards
给你一个序列,再给你一个数,让你算出这个序列里有多少个子序列的平均值为A。
我们利用动态规划求解,利用来记录前i个数里选j个数总和为k的方案数。
因为最大的运算结果是k=50*50=2500,而j和i都可以取50所以最大为,如果我们#define int long long 的话会爆掉,long long无法存下,所以我们考虑滚动数组。我们发现每一层i都是由上一层i-1来决定的,因此我们只需要保存两个状态就好了。状态的转移是,对于一个新的循环。他可以继承上一轮选了j个数总和为z的方案数,如果他当前表示的“和”(z)大于当前要判断的数a[i]的话,那么他就可以在继承的基础上,再加上上一轮选了j-1个数,总和为z-a[i]的结果。最后判断在所有n个数里选i(1<=i<=n)个数,平均数是A的结果。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>
const int N=51;
int dp[2][N][N*N];
int a[55];
int sum[55];
void solve() {
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
int now=1;
dp[1][0][0]=dp[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
for(int z=0;z<=sum[i];z++){
dp[now][j][z]=dp[now^1][j][z];
if(z>=a[i]){
dp[now][j][z]+=dp[now^1][j-1][z-a[i]];
}
}
}
now^=1;
}
int sum=0;
for(int i=1;i<=n;i++){
sum+=dp[now^1][i][i*m];
}
cout<<sum<<endl;
}
signed main() {
ios::sync_with_stdio ( false );
cin.tie ( nullptr );
cout.tie ( nullptr );
int oyyo = 1;
//cin >> oyyo;
while ( oyyo-- ) {
solve();
}
return 0;
}
Nearest Excluded Points
题目给了你n个红点,让你去找每个红点周围的点,满足这个点在红点队列里,并且距离当前红点的曼哈顿距离最小。
红点一共有两种状况,①上下左右不全是红点。②上下左右全是红点。
对于第一种情况。我们可以直接去找这个点的上下左右。找到了就是最短。
对于第二种情况,因为他是被红点包围的,我们就从“边缘”上的红点(已经找到最短曼哈顿距离点的红点)出发,向内去缩小未知点范围。(如果这个点A周围有一个已经找到最近曼哈顿点C的红点B,那么这个曼哈顿点C,同样是新红点A的最近曼哈顿点)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
void solve() {
int n;
cin>>n;
vector<pair<int,int>>a(n);
for(int i=0;i<n;i++){
cin>>a[i].first>>a[i].second;//每个红点的信息
}
set<pair<int,int>>st(a.begin(),a.end());//筛选红点。
map<pair<int,int>,pair<int,int>>u;
queue<pair<int,int>>q;
for(auto c:a){//对于一个红点遍历他的周围,用来判断一个点周围全是红点的状况。
for(int i=0;i<4;i++){
int nx=c.first+dx[i],ny=c.second+dy[i];
if(st.count({nx,ny})){
continue;//如果是红点。跳过。
}
u[{c.first,c.second}]={nx,ny};
//只要周围有一个不是红点,那么这个点到红点的距离就是1,这个就是最近的点。
q.push({c.first,c.second});//现在可以把这个点塞到队列中,用来解决一个点周围全是红点的状况。
break;//这个点已经找到离他最近的点了,可以break,判断下一个点了。
}
}
//现在开始找一个红点周围全是红点包围的情况。
while(!q.empty()){//遍历所有的红点。
int x=q.front().first,y=q.front().second;
q.pop();
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(!st.count({nx,ny}) or u.count({nx,ny})){
continue;//遍历这个红点的周围。如果它不是被标记的红点,或这个红点已经被判断过(说明他不是周围全是红点的红点。我们已经找过了)
}
u[{nx,ny}]=u[{x,y}];//然后这个点的最近点就是他周围红点的最近点。这样距离是最小。
q.push({nx,ny});//现在这个新点也被找到了,可以加到队列里,用来去找更加内部的点了。
}
}
for(auto& c:a){//输出
auto it=u[{c.first,c.second}];
cout<<it.first<<" "<<it.second<<endl;
}
}
signed main() {
ios::sync_with_stdio ( false );
cin.tie ( nullptr );
cout.tie ( nullptr );
int oyyo = 1;
//cin >> oyyo;
while ( oyyo-- ) {
solve();
}
return 0;
}