总结
今天开局看1004过了一车人,跟队友一会大胆猜测全部都是No,直接莽了一发过了,然后队友开1006我开1007,队友10min过1006,我写一半发现1007读假题看复杂了,重新思考后一发过了1007,两个队友继续看1001,我开1002图论,写了一发t了,又写了几发优化了常数,还是t,遂让队友用奇技淫巧——卡时,卡了三次之后莫名其妙的过了1002,然后队友又看出1011线性基,一发又秒了,五题,我继续找图论1005,队友看1001,最后10min队友过了1001,我没做出来1005,6题结束。
题解
1004 - Link with Equilateral Triangle
题意:
一个边长为 n n n 的大三角形,由 n 2 n^2 n2 个小三角形组成,用 0 , 1 , 2 0,1,2 0,1,2 填小三角形的三个角,其中大三角形左边不能填 0 0 0 ,右边不能填 1 1 1 ,下边不能填 2 2 2 。问:给出 n n n ,是否能填出一个三角形使每个小三角形三个点之后不为 3 3 3 的倍数。
做法:
输出“No”
代码:略
1006 - BIT Subway
题意:
有人买地铁票,如果当月已买 100 100 100 元则打八折,如果当月已买 200 200 200 元则打五折, D L e e DLee DLee 认为如果自己当月已买了 199 199 199 元的票后如果再买 10 10 10 元的票,自己总共需要付的钱为 199 + 1 / 0.8 + ( 10 − 1 / 0.8 ) ∗ 0.5 199+1/0.8+ (10-1/0.8)*0.5 199+1/0.8+(10−1/0.8)∗0.5 元,但实际并不如此,给定 t t t 个月的买票数据,每个月买了 n n n 张票,问按 D L e e DLee DLee 的方法算买票钱和正常方法算买票钱各自的结果是多少。
做法:
模拟题,正常方法就用正常方法模拟, D L e e DLee DLee 的方法则讨论一下即可。
代码:
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
const int inf = 0x3f3f3f3f;
int t;
int n,m,k;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
vector<double> a(n);
for(int i=0;i<n;i++)
{
cin>>m;
a[i]=m;
}
double ans1=0,ans2=0;
for(int i=0;i<n;i++)
{
if(ans2<100.0)
ans2+=a[i];
else if(ans2<200.0)
ans2+=a[i]*0.8;
else
ans2+=a[i]*0.5;
}
for(int i=0;i<n;i++)
{
if(ans1<100.0)
{
if(a[i]+ans1>100.0)
{
a[i]-=(100.0-ans1);
ans1=100.0;
i--;
}
else
ans1+=a[i];
}
else if(ans1<200.0)
{
if(a[i]*0.8+ans1>200.0)
{
a[i]-=(200.0-ans1)/0.8;
ans1=200.0;
i--;
}
else
ans1+=a[i]*0.8;
}
else
ans1+=a[i]*0.5;
}
cout<<fixed<<setprecision(3)<<ans1<<" "<<ans2<<endl;
}
return 0;
}
1007 - Climb Stairs
题意:
一种打怪游戏,角色初始武力值为 a 0 a_0 a0 ,初始位置为 0 0 0 ,攻击范围为 k k k ,角色每次可以向前打当前位置 + k +k +k 的怪,也可以每次向后一格打怪,角色能打败的怪物的武力值需要小于等于角色当前的武力值,每次杀死一个怪都会获得杀死怪的武力值,且不能访问已经到达过的位置。问是否能够将所有的 n n n 个怪消灭。
做法:
预处理 n n n 个怪的前缀和以及打败第 k k k 个怪之后通过后退操作将第 k k k 个怪前面所有的怪都打败所需的武力值,然后每次贪心找第一个能够打败前面的怪物并且回退时能够将之前所有怪清除的位置 x x x ,打完之后将 x x x 及之前未死亡的所有怪的武力值增加到当前的武力值上,继续向后贪心。复杂度 O ( n ) O(n) O(n).
代码:
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn =100010;
int t;
int n,m,k;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
int now;
cin>>n>>now>>k;
vector<int> a(n+1,0),sum(n+1,0);
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];//预处理怪物武力值的前缀和
a[i]=max(a[i-1]-a[i],a[i]);//预处理击败第i个怪同时清除第i个怪之前所有怪所需的武力值
}
int l=1,r=k,x=0,num=0;//l为下一个怪的位置,r为从当前位置最多能打到后面第几个怪
while(x!=n)
{
bool f1=true;
for(int i=l;i<=r;i++)
{
if(now>=a[i])//找到第一个能杀死当前怪物且能把后面怪物清空的位置
{
now+=sum[i]-sum[x];//将杀死怪物的武力值加上
num+=i-x;//记下杀死怪物的个数
r=min(l+k,n);//更新
l=i+1;
x=i;
f1=false;
break;
}
}
if(f1)//没找到,break
break;
}
if(num==n)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
1011 - Link is as bear
题意:
给一个数组 a i ( 1 ≤ i ≤ n ) a_i(1\le i \le n) ai(1≤i≤n) ,可以对数组进行操作:每次选定两个整数 l , r ( 1 ≤ l ≤ r ≤ n ) l,r(1\le l \le r \le n) l,r(1≤l≤r≤n),令所有 a i = x o r ( a [ l ] , … , a [ r ] ) a_i=xor(a[l],…,a[r]) ai=xor(a[l],…,a[r]),问,在进行任意操作后要让数组中所有数相同,请问这个数的相同值最大是多少。
做法:
线性基板子,把所有数的插入到线性基里面 x o r xor xor 后输出答案即可,顺便贴一个题解的证明:
代码:
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using ull = unsigned long long;
using namespace std;
const int inf = 0x3f3f3f3f;
int t;
int n,m,k;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
vector<ull> B;
auto insert = [&](ull x)
{
for(auto b:B)
x=min(x,b^x);
for(auto &b:B)
b=min(b,b^x);
if(x)
B.push_back(x);
};
cin>>n;
for(int i=0;i<n;i++)
{
cin>>m;
insert(m);
}
int ans=0;
for(auto x:B)
ans^=x;
cout<<ans<<endl;
}
return 0;
}