A Seventeen
题目大意:给定一个数,用1~n的每个数,使用+ - * ( )运算符号,每个数仅可以使用一次,使其结果为17, 这个组合有很多个,任意写出一个,如果找不到这样的组合数,输出-1。
思路:如1 2 3 4 一样,1-2-3+4=0,四个数为一个循环,只找到开头的四个数,剩下的循环即可,分析可知:1~3找不到这样的组合数,输出-1,开头的四个数为4 5 6 7。
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
cin>>n;
if(n>=1&&n<=3)
cout<<"-1";
else
{
int t=n%4;
if(t==0)
{
if(n==4)
cout<<"3*(1+4)+2";
else
cout<<"3*(1+4)+2"<<'+';
for(int i=5;i<=n;i++)
{
if(i%4==1) cout<<i<<'-';
else if(i%4==2) cout<<i<<'-';
else if(i%4==3) cout<<i<<'+';
else
{
if(i==n) cout<<i;
else cout<<i<<'+';
}
}
}
else if(t==1)
{
if(n==5)
cout<<"(2-1)*3*4+5";
else
cout<<"(2-1)*3*4+5"<<'+';
for(int i=6;i<=n;i++)
{
if(i%4==2) cout<<i<<'-';
else if(i%4==3) cout<<i<<'-';
else if(i%4==0) cout<<i<<'+';
else
{
if(i==n) cout<<i;
else cout<<i<<'+';
}
}
}
else if(t==2)
{
if(n==6)
cout<<"1-2-3*4+5*6";
else
cout<<"1-2-3*4+5*6"<<'+';
for(int i=7;i<=n;i++)
{
if(i%4==3) cout<<i<<'-';
else if(i%4==0) cout<<i<<'-';
else if(i%4==1) cout<<i<<'+';
else
{
if(i==n) cout<<i;
else cout<<i<<'+';
}
}
}
else if(t==3)
{
if(n==7)
cout<<"-1*(2+3)-4*5+6*7";
else
cout<<"-1*(2+3)-4*5+6*7"<<'+';
for(int i=8;i<=n;i++)
{
if(i%4==0) cout<<i<<'-';
else if(i%4==1) cout<<i<<'-';
else if(i%4==2) cout<<i<<'+';
else
{
if(i==n) cout<<i;
else cout<<i<<'+';
}
}
}
}
return 0;
}
E Subsegments
题目大意:给定数n x;接下来输入n个数,将数组中的数按照次序相乘,找到其积为x的值,求这样的组合数符合条件的一共有多少个。
思路:可以将两种情况进行分析,即存在0和不存在0两种情况。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int N=5e5+10;
ll a[N],n,x,ans=0,sum=1;
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)
cin>>a[i];
//有两种可能性,x=0,x!=0;
if(x==0)
{
int last=0;
for(int i=1;i<=n;i++)
if(a[i]==0)
{
ans+=(i-last)*(n-i+1);
last=i;
}
cout<<ans;
}
else
{
map<int,int>heap;//维护;
heap[x]=1;
for(int i=1;i<=n;i++)
{
if(a[i]!=0)
{
sum=sum*a[i]%mod;
ans+=heap[sum];
heap[sum*x%mod]++;
}
else
{
sum=1;
heap.clear();
heap[x]=1;
}
}
cout<<ans;
}
return 0;
}
K Coins
题目大意:给定硬币的额度,给定一个数,看A B哪个用的查询的答案是获取该值所需的最小硬币数,如果无法获得该值,则答案为−1.如果它们都可以获得最小数字,则输出“both”
思路:由已知条件可知,当给定数字大于两人硬币最大额度乘积时,明显是A的硬币数出的最少。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 13*19+10;
int c1[5] = {0,2,3,17,19};
int c2[5] = {0,5,7,11,13};
int f[N],g[N];
int main()
{
memset(f,0x3f,sizeof f);
memset(g,0x3f,sizeof g);
f[0] = 0;
g[0] = 0;
for(int i = 1;i<=4;i++)
{
for(int j = c1[i];j<N;j++)
f[j] = min(f[j-c1[i]]+1,f[j]);
for(int j = c2[i];j<N;j++)
g[j] = min(g[j-c2[i]]+1,g[j]);
}
int q;
cin>>q;
while(q--)
{
int x;
scanf("%d",&x);
if(x==1)
puts("-1");
else if(x>=N)
puts("A");
else
{
if(f[x]==g[x])
puts("both");
else if(f[x]<g[x])
puts("A");
else
puts("B");
}
}
return 0;
}
**
H Counting
**
题目大意:在一张 n × m 的网格图上,给定 k 个人在 0 ∼ T 秒内的行动路
线(每秒只能走一步),求每秒重叠的人的对数。
思路:对于网格图的每一个位置维护,根据每一个人的移动情况修改,同时维护答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=3e3+10;
int mp[N][N],x[N],y[N];
char s[N][N];
int n,m,k,t;
int main()
{
cin>>n>>m>>k>>t;
for(int i=1;i<=k;i++)
{
scanf("%d %d",&x[i],&y[i]);
}
for(int i=1;i<=k;i++)
{
cin>>s[i];
}
for(int i=0;i<=t;i++)
{
int ans=0;
for(int j=1;j<=k;j++)
{
ans=ans+mp[x[j]][y[j]];
mp[x[j]][y[j]]++;
}
cout<<ans<<endl;
if(i==t) break;
for(int j=1;j<=k;j++)
{
mp[x[j]][y[j]]=0;
if(s[j][i]=='L') y[j]--;
if(s[j][i]=='R') y[j]++;
if(s[j][i]=='U') x[j]--;
if(s[j][i]=='D') x[j]++;
}
}
return 0;
}