1001 Maximum Multiple
题意:给出n,找x,y,z,n=x+y+z,x|n,y|n,z|n,求x*y*z的最大值
思路:因为整除关系,所以(x+y+z)/n=1/(n/x)+1/(n/y)+1/(n/z),得是1/2,1/3,1/4.。。。其中三个,分母是n因子,并且和为1.
然后写写,就三种情况,1/3+1/3+1/3,1/2+1/4+1/4,1/2+1/3+1/6,又因为有1/3 的情况一定是三个1/3最大。所以最后一种也是不可能选择,很简单
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,a,b,c,t,ans;
int main()
{
scanf("%lld",&n);
while(n--)
{
scanf("%lld",&t);
ans=-1;
if(t%2==0&&t%3==0&&t%6==0)
{
ans=max(ans,t/2*t/3*t/6);
}
if(t%2==0&&t%4==0)
{
ans=max(ans,t/2*t/4*t/4);
}
if(t%3==0)
{
ans=max(ans,t/3*t/3*t/3);
}
printf("%lld\n",ans);
}
return 0;
}
1002 Balanced Sequence
题意:n个括号序列,随意连接成一个串,求匹配的括号的个数
思路:贪心,每个字符串预处理,留下左面的连续)和右面的连续(,中间已经匹配上的括号个数算出来,然后就是排序方式是对任意两个序列,组成新括号多 的靠左,相等时,左括号多的在左,避免右括号较多,前面的左括号不够导致形成的新括号不是最多的、,画个图能更好理解,让左括号尽量多的靠左,前缀的右括号要尽量比左括号多,或者尽量少的小一点。
因为这个题比赛的时候没A,不过想到了贪心思路,也知道是左右免得个数排序有关,但是没有明确思路,所以没有敲出来。然后赛后看直播时,大佬说如果实在想不出来,各种排序都试试,总一种是对的???真是涨姿势了!!详见代码。
代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
char S[500000];
struct node
{
int l,r;
}data[500000];
int cmp(node a,node b)
{
int x= min(a.l,b.r);
int y = min(a.r,b.l);
return x>y|(x==y&&a.l>b.l);//排序方式是对任意两个序列,组成新括号多 的靠左,相等时,左括号多的在左,避免右括号较多,前面的左括号不够导致形成的新括号不是最多的
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
long long ans = 0;
for(int i=1;i<=n;i++)
{
scanf("%s",S);
int len = strlen(S);
int tmp_l = 0,tmp_r = 0;
for(int j=0;j<len;j++)//对每个序列,ans加上它内部完整的括号对,并计算除去中间的括号对。多余的左括号数和右括号数
{
if(S[j]=='(')
tmp_l++;
else
{
if(tmp_l>0)
{
tmp_l--;
ans++;
}
else tmp_r++;
}
}
//cout<<tmp_l<<" "<<tmp_r<<endl;
data[i].l = tmp_l;
data[i].r = tmp_r;
}
sort(data+1,data+1+n,cmp);
// for(int i=1;i<=n;i++)
// cout<<data[i].l<<" "<<data[i].r<<endl;
int tmp_ll = 0;
for(int i=1;i<n;i++)//序列排序已经确定,计算形成新的括号数
{
ans+=min(data[i].l,data[i+1].r);//加上相邻的两个序列形成的新的括号对数
int o = data[i+1].r-min(data[i].l,data[i+1].r);//第i+1个序列剩下的右括号数
ans+=min(o,tmp_ll);//i+1与i在v和后剩余的右括号与前i-1个序列剩下的左括号形成的新括号对数
tmp_ll-=min(o,tmp_ll);//计算前i-1个位置剩余的左括号
tmp_ll = tmp_ll+ data[i].l-min(data[i].l,data[i+1].r);//加上第i个位置剩下的左括号
}
cout<<ans*2<<endl;
}
return 0;
}
1003 Triangle Partition
题意:3*n个点,任意三点之间都不再一条直线上(任意三点都能组成一个三角形),求一种组合成n个三角形,任意三角形之间不相交。
思路:很水,给x和y排排序。然后一次输出,一行输出三个点的标号就可以了。。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxN=1e3+5;
struct Node{
int x,y,id;
bool operator < (const Node & obj)const
{
if(x!=obj.x) return x<obj.x;
else return y<obj.y;
}
}p[maxN*3];
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=3*n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
p[i].id=i;
}
sort(p+1,p+3*n+1);
for(int i=1;i<=3*n;i+=3)
{
printf("%d %d %d\n",p[i].id,p[i+1].id,p[i+2].id);
}
}
return 0;
}
1004 Distinct Values
题意:n个点,m个区间,每个区间内的所有数不相同,给每个点赋值,求符合要求的最小字典序
思路:贪心,先按照区间左端点从小到大排序,右端点从大到小,然后去掉某些是其他区间的子区间的 区间,然后没有被区间覆盖的点,一定是放1,,,左端点开始的某部分若与前面的区间不重复,那么就说明,不受前面区间的影响,从1开始放,若重合一部分,那么重合的部分已排好,剩下的部分从前面没有的数中,从小的开始往里放,,
对于要往里放的数,可以用优先队列或者set存一下,没有放的数放在集合里,从左往右遍历,要放数的时候就从队列顶部出一个赋值,每个区间考虑完,要将与下一区间不重合的部分的数重新加入队列。这样只有2n的循环
代码:
(PS: 思路是自己的思路,但是比赛的时候因为set没用好,T了?最后是队友用同样思路敲的,A了。。。然后懒得敲了,直接上队友代码了。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include <sstream>
#define inf 800000000
#define ll long long
#define mod 1000000007
using namespace std;
struct fuck
{
int l,r,len;
}a[100010];
bool cmp(const fuck &x,const fuck &y)
{
if(x.l==y.l)
return x.len>y.len;
return x.l<y.l;
}
struct cmp1
{
bool operator ()(int &x,int &y)
{
return x>y;//最小值优先
}
};
int res[100010];
int main()
{
int T;
scanf("%d",&T);//cin>>T;
while(T--)
{
int n,m,i,cnt;
priority_queue<int,vector<int>,cmp1>que;//最小值优先
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].len=a[i].r-a[i].l+1;
}
for(i=1;i<=n;i++)
{
que.push(i);
}
sort(a,a+m,cmp);
cnt=1;
int cnt2=1;
for(i=0;i<m;i++)
{
while(cnt<a[i].l)
{
res[cnt++]=1;
}
while(cnt2<a[i].l)
{
if(res[cnt2]==1&&que.top()==1)
{
cnt2++;
}
else
que.push(res[cnt2++]);
}
while(cnt<=a[i].r)
{
res[cnt++]=que.top();
que.pop();
}
}
while(cnt<=n)
{
res[cnt++]=1;
}
printf("%d",res[1]);
for(i=2;i<=n;i++)
{
printf(" %d",res[i]);//cout<<res[i]<<" ";
}
printf("\n");
}
}
1007 Chiaki Sequence Revisited
题意:题目给出a【n】的表达式 了,求a[1]--a[n]的所有数的和
思路:可以算是规律题?打表能发现,a是单调不减序列,每个数出现的次数是lowbit(i)次,然后可以得出每个奇数出现一次,
2的k次方开始的等差为2的k次方的序列的每个数出现k+1次,然后二分就能求?,反正比赛的时候打表没发现这规律。。。看出一点苗头,却没有往lowbit上想,,,明天在补这个题。。
(PS:标称还没看懂,但是看了另一位大佬的博客,写的挺好的)
https://blog.csdn.net/ACTerminate/article/details/81173935
代码:
1011 Time Zone
题意:给出东八区的时间,求目标失去的时间。
思路:就是一个很复杂的大模拟,,很多细节,队友做的,,坐了很久,,终于A了,,算是恶心的签到题!
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include <sstream>
#define inf 800000000
#define ll long long
#define mod 1000000007
using namespace std;
int geth (string s)
{
int i,now=0;
for(i=4;i<s.length();i++)
{
if(s[i]=='.')
{
break;
}
now=now*10+(s[i]-'0');
}
return now;
}
int getm (string s)
{
int i,now=0;
bool f=0;
for(i=4;i<s.length();i++)
{
if(s[i]=='.')
{
f=1;
continue;
}
if(f)
{
now=now*10+(s[i]-'0');
}
}
now=now*6;
return now;
}
int main()
{
int n;
scanf("%d",&n);//cin>>n;
while(n--)
{
int h,m;
char s[100];
scanf("%d%d",&h,&m);//cin>>h>>m;
scanf("%s",s);
if(s[3]=='+')
{
m+=getm(s);
if(m>=60)
{
h++;
m%=60;
}
h+=geth(s);
h-=8;
if(h<0)
{
h+=24;
}
h%=24;
if(h<10)
{
printf("0%d",h);//cout<<0<<h;
}
else
{
printf("%d",h);//cout<<h;
}
printf(":");//cout<<":";
if(m<10)
{
printf("0%d",m);//cout<<0<<m;
}
else
{
printf("%d",m);//cout<<m;
}
printf("\n");//cout<<endl;
}
else
{
m-=getm(s);
if(m<0)
{
h--;
m+=60;
}
h-=geth(s);
h-=8;
if(h<0)
{
h+=24;
}
h%=24;
if(h<10)
{
printf("0%d",h);//cout<<0<<h;
}
else
{
printf("%d",h);//cout<<h;
}
printf(":");//cout<<":";
if(m<10)
{
printf("0%d",m);//cout<<0<<m;
}
else
{
printf("%d",m);//cout<<m;
}
printf("\n");//cout<<endl;
}
}
}