UPC2021级新生个人训练赛第31场
好久没总结了。主要是,之前那几场,大都不会,心态崩溃,摆烂还掉队。。
这次对了8道,有了点信心,最后2两道是后来借鉴大佬做法做出来的
问题 A: 幸运数字
签到题。。。
#include<iostream>
using namespace std;
typedef long long LL;
int main()
{
LL n,ans=0;
cin>>n;
LL x;
while(n--)
{
cin>>x;
if(x%4==0||x%7==0)
ans+=x;
}
cout<<ans;
return 0;
}
问题 B: 对撞
这个题逻辑上也没啥难度,就是在实现的时候出了几次小错误。还有一开始看到数据范围以为要写高精就先跳过去了
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
vector<int>x;
vector<int>y;
int main()
{
string a,b;
cin>>a>>b;
int xa=0,xb=0;
for(int i=0;i<a.length();i++)
{
if(a[i]==b[i])
x.push_back(a[i]-'0'),y.push_back(b[i]-'0');
else
if(a[i]>b[i])
x.push_back(a[i]-'0'),xa++;
else
y.push_back(b[i]-'0'),xb++;
}
if(xb<a.length())
{
int i=0;
while(x[i]==0&&i<x.size())i++;
if(i==x.size())cout<<0;
for(;i<x.size();i++)
cout<<x[i];
}
else
cout<<"BOOM";
cout<<endl;
if(xa<a.length())
{
int i=0;
while(y[i]==0&&i<y.size())i++;
if(i==y.size())cout<<0;
for(;i<y.size();i++)
cout<<y[i];
}
else cout<<"BOOM\n";
return 0;
}
问题 C: 差值求和
先排序,两两之间的绝对值可以用大的减小的,然后暴力,果断TLE。
找规律。。如果是5 1 2 3 4 5会怎么样ans= 5-4 + 5-3 +5-2 +5-1........+2-1最后一加和是4个5+2个4+0个3-2个2-4个1.然后这题就不会超时了
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL n;
LL a[100005];
LL ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
int m=n-1;
for(int i=n;i>0;i--,m-=2)
ans+=(LL)a[i]*m;
cout<<ans;
return 0;
}
问题 D: 取数游戏
这个是我最后困扰的题,问题出在最后的每两个都要计算一下。TLE无解。。
赛后参照ytj大佬的代码,直呼妙啊~
这个的思路就是:从小到大排序,统计每个数字的个数,大于二的可以符合条件,可能的次数为个数*(个数-1).然后两两相乘,像C一样,暴力肯定会TLE
如何用O(n)实现O(n *n)的操作呢
这里我们是求和。假设有n个数两两相乘 a1,a2,...an ans=a1 *a2 +a1 *a3+.....+a1 *an +a2 *a3.......又可以反过来ans= an *a1+ an *a2+ ....+an * a(n-1)...+a(n-1) * a1........
发现没有 ?反过来后更好识别,ans就是2-n时 ai * sumi的和。这里问题就解决啦。
#include<iostream>
#include<map>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
LL n,ans;
vector<int>a;
map<int,int>b;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(b[x]==0)
a.push_back(x);
b[x]++;
}
sort(a.begin(),a.end());
for(int i=0;i<a.size();i++)
{
if(b[a[i]]==1)continue;
b[a[i]]=b[a[i]]*(b[a[i]]-1)%1000000007;
}
LL sum=b[a[0]];
for(int i=1;i<a.size();i++)
{
if(b[a[i]]==1)continue;
ans+=sum*b[a[i]];
sum+=b[a[i]];
ans%=1000000007;
sum%=1000000007;
}
cout<<ans;
return 0;
}
问题 E: 哈夫曼编码
一开始以为要用到树相关的知识来,这些现在还不会,幸好这个题不是哈夫曼树,比较简单
统计,排序,基本操作
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
map<char,int>num;
struct letter
{
char l;
int su;
}A[30];
bool cmp(letter a,letter b)
{
if(a.su>b.su)
return 1;
if(a.su==b.su)
return a.l<b.l;
if(a.su<b.su)
return 0;
}
typedef long long LL;
string k;
int t=1;
int main()
{
cin>>k;
for(int i=0;i<k.length();i++)
{
if(num[k[i]]==0)
num[k[i]]=t,t++;
A[num[k[i]]].l=k[i];
A[num[k[i]]].su++;
}
sort(A+1,A+t,cmp);
for(int i=1;i<t;i++)
cout<<A[i].l<<' '<<A[i].su<<endl;
return 0;
}
问题 F: 智力大奖赛
emmm真就是一个找规律的题了,数列的一些知识不能忘。
小三角形是一个1 3 5 7 ......2 * n-1的一个等差数列 ans = n * n
能量棒我们可以只看横着的一条边1 2 3 4 5 6 ..... n的等差数列 ans = (n+1)n/2
最后别忘了 * 3
#include<iostream>
using namespace std;
typedef long long LL;
LL n;
int main()
{
cin>>n;
cout<<n*n<<endl;
cout<<(1+n)*n/2*3;
return 0;
}
问题 G: 求素数I
数据不大,直接暴力。
按照题意,挨个取,判断质数即可,然后经典的排序输出
#include<iostream>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,l;
int a[101];
int b[101],t=0;
map<int,bool>h;
bool prime(int x)
{
if(x<2)
return 0;
for(int i=2;i<sqrt(x);i++)
if(x%i==0)
return 0;
return 1;
}
int main()
{
cin>>n>>l;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n-l+1;i++)
{
int x=a[i];
if(a[i]==0)continue;
for(int j=i+1;j<i+l;j++)
x=x*10+a[j];
if(prime(x)&&(h[x]==0))
{
b[t]=x;
h[x]=1;
t++;
}
}
sort(b,b+t);
for(int i=0;i<t-1;i++)
cout<<b[i]<<',';
cout<<b[t-1];
return 0;
}
问题 H: 立方和
这个题其实我还是有点疑问的。不过既然A了,也就问题不大了
递归解决即可,就是不符合条件至少走多少次令我困惑
#include<iostream>
using namespace std;
typedef long long LL;
int ans;
inline int po(int x)
{
return x*x*x;
}
void work(int n,int l,int k)
{
if(n==l)
{
ans=n;
return;
}
if(k==999)return;
n%=1000;
work(po(n/100)+po(n/10%10)+po(n%10),n,k+1);
}
int main()
{
int n;
cin>>n;
work(n,0,0);
if(ans)
cout<<ans;
else cout<<"error";
return 0;
}
what?学校网站又访问不了了??
凭印象写写吧
I:最大和最小
这个也类似数学吧。如果按照正常的运算顺序结果是最小的,如果先算加法再乘法,结果是最大的。我想到了,可是实现的时候失败了,后来赛后还是看的CSDN上一位大佬的才做出来。
数学证明咱没能力
#include<iostream>
#include<cctype>
using namespace std;
typedef long long LL;
char lk[101];
LL a[100],b[100],t=1;
int main()
{
cin>>a[1];
b[1]=a[1];
while(cin>>lk[t])
{
if(lk[t]=='=')break;
cin>>a[++t];
b[t]=a[t];
}
LL x=0;
LL k=1;
for(int i=1;i<t;i++)
{
if(lk[i]=='*')
{
a[i+1]=a[i]*a[i+1];
a[i]=0;
}
if(lk[i]=='+')
{
b[i+1]=b[i]+b[i+1];
b[i]=1;
}
}
for(int i=1;i<=t;i++)
{
x+=a[i];
k*=b[i];
}
cout<<k<<endl;
cout<<x;
return 0;
}
J:电话
这村子摊上这个村长可真是倒霉到家了。什么癖好?
这个其实不难,按照序号排序,剩下和那个栅栏翻新就一样了。此处不多赘述
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL n,m,ans;
struct tracker
{
int s;
int r;
}t[1000001];
bool cmp(tracker a,tracker b)
{
return a.s<b.s;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>t[i].s>>t[i].r;
sort(t+1,t+1+n,cmp);
for(int i=1;i<=n;i++)
if(t[i].r>t[i-1].r)ans+=(t[i].r-t[i-1].r);
cout<<ans;
return 0;
}
晚安
-------------------------------------------
个性签名:曾经的我们空有一颗望海的心,却从没为前往大海做过真正的努力
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!