这场是dls出的题,感觉dls出的题特别有意思~
补题进度 : 5/11
1001
题意把一个数拆分成三个数,这三个数是原来的数的因子
既然是因子,那么等式 n=x+y+z n = x + y + z ,边同时除以N,就会发现一个神奇的东西,然后判断下能否被3或者4整除就行。
#include
#include
using namespace std;
#define mod 1000000007
typedef unsigned long long ll;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll T,n;
cin>>T;
while(T--)
{
cin>>n;
ll x;
if(n%3==0)
x=(n/3)*(n/3)*(n/3);
else if(n%4==0)
x=(n/2)*(n/4)*(n/4);
else
{
cout<<"-1\n";
continue;
}
cout<"\n";
}
return 0;
}
ps:比赛的时候是打表找出来的……
1002:
这道题的题意是给出多个括号序列,然后问你不要求连续的括号匹配的长度是多少。
不要求连续的话首先我们可以先处理每个字符串中已经匹配的括号个数和没有匹配的左右括号个数,然后就想到了排序试一下。
有很多种排序方式,贪心的想的话,如果比较两个序列时,我们会让当前的两个括号序列提供更多的匹配个数。如果能够提供的匹配是一样的,我们会让更多的左括号在前边,这样就会提供更多的右括号给之后的序列。
#include
#define ll long long
#define pii pair
#define x first
#define y second
using namespace std;
const int maxn = 1e5 + 5;
struct seq
{
int a,b,cnt;
}a[maxn];
char temp[maxn];
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
int n;
scanf("%d", &n);
// memset(a,0,sizeof(a));
for(int i = 1;i<=n;i++)
{
scanf("%s", temp);
a[i].a = a[i].b = a[i].cnt = 0;
for(int j = 0;j<strlen(temp);j++)
{
if(temp[j] == '(')
{
a[i].a++;
}
else
{
if(a[i].a)
{
a[i].a--;
a[i].cnt++;
}
else
{
a[i].b++;
}
}
}
}
sort(a+1,a+n+1,[](seq a,seq b)
{
int x = min(a.a,b.b);
int y = min(a.b,b.a);
return x > y || (x == y && a.a > b.a);
});
int ans = 0,now = 0;
for(int i = 1;i<=n;i++)
{
int temp = min(a[i].b,now);
ans += temp + a[i].cnt;
now = now + a[i].a-temp;
}
printf("%d\n",ans * 2);
}
return 0;
}
1003
这道题的题意就是给出3n个互不共线的点,问如何构造n个三角形,让他们不相交。
这道题的正解是先求一个凸包,然后在凸包上找一条边,然后再找一个和这条边夹角最小的点,然后删除掉这些点,再求一次凸包……直到取N次之后,这样肯定是有解的,然而因为题目中明确了不会出现三点共线的情况,也就是说只要排序后按顺序取三个点就能完成目标了。
#include
#define ll long long
#define pii pair
#define x first
#define y second
using namespace std;
const int maxn = 3e4+5;
pairint> a[maxn];
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
int n;
scanf("%d", &n);
for(int i = 1;i<=3*n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
a[i] = make_pair(make_pair(x,y),i);
}
sort(a+1,a+3*n+1);
for(int i = 1;i<=n;i++)
{
printf("%d %d %d\n",a[3*i].y,a[3*i-1].y,a[3*i-2].y);
}
}
return 0;
}
1004
这道题的题意是给出队医一个长度为n的数组的m个查询的情况,每次查询的al~ar都是互不相同的,现在求出符合要求的字典序最小的数组。
得出数组本身不难,只要先将查询区间按照一定顺序排序,或者按照区间的覆盖情况尽心划分。之后按照数组的划分情况填入数字就行。
字典序最小的情况,也就是说每个被划分的数组都是由最小的开始,那么我们可以用一个set或者优先队列维护一下当前没有使用过的最小值(MEX),在更新过后一段区间之后,我们只要把这一段使用过的数组添加回set或者优先队列中就行了。
#include
#define ll long long
#define pii pair
#define x first
#define y second
using namespace std;
const int maxn = 1e5 + 5;
int ans[maxn];
int lmost[maxn];
int main()
{
int ca;
scanf("%d",&ca);
set<int> mex;
while(ca--)
{
int n,m;
scanf("%d%d", &n,&m);
for(int i = 1;i<=n;i++) lmost[i] = i;
for(int i = 0;iint l,r;
scanf("%d%d", &l,&r);
lmost[r] = min(lmost[r],l);
}
for(int i = n-1;i>=1;i--)
{
lmost[i] = min(lmost[i],lmost[i+1]);
}
mex.clear();
for(int i = 1;i<=n;i++) mex.insert(i);
for(int i = 1,j = 1;i<=n;i++)
{
while(j < lmost[i])
{
mex.insert(ans[j++]);
}
ans[i] = *mex.begin();
mex.erase(ans[i]);
}
for(int i = 1;i<=n;i++)
{
printf("%d%c",ans[i],i == n ? '\n':' ');
}
}
return 0;
}
1011
水题一个,注意小数点切分就行
#include
#define ll long long
#define x first
#define y second
using namespace std;
void tran(int &a)
{
a -= 8;
if(a < 0)
a += 24;
}
int get_time(char s[])
{
int x = 0,y = 0;
int base = 60;
int sgn = (s[0] == '+' ? 1 : -1);
for(int i = 1;i<strlen(s);i++)
{
if(s[i] == '.')
{
y = s[i+1] - '0';
break;
}
else
{
x*=10;
x += (s[i] - '0');
}
}
return sgn*(x * 60 + y * 6);
}
char f[10];
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
int a,b;
scanf("%d %d UTC%s",&a,&b,f);
tran(a);
int t = get_time(f);
if(t < 0)
{
t = -t;
b = (b - (t%60));
if(b <0)
{
b += 60;
a--;
}
a = a - (t/60);
if(a < 0)
{
a += 24;
}
}
else
{
b = (b + (t % 60));
if(b >= 60)
{
b -= 60;
a++;
}
a += (t/60);
if(a >= 24)
{
a -= 24;
}
}
printf("%02d:%02d\n",a,b);
}
return 0;
}