感觉每次自己没赶上的比赛vitural做起来都格外的顺手.每次赶上的都做的格外难受:(
这场的A-D都比较简单.
A.Sequence with Digits
题目大意:定义了一种关系an+1 = an + maxdig(an)*mindig(an).这里的max和min指的是十进制下an的最大的数和最小的数.给了a1和k求ak.
因为迟早会出现0.这个时候就不会改变了.所以暴力的做就好了.
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#include
using namespace std;
const int N = 2e5+10;
inline int read(){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int t;
LL solve(LL x){
LL m1 = -1,m2 = 10;
while(x){
m1 = max(m1,x%10);
m2 = min(m2,x%10);
x/=10;
}
return m1*m2;
}
int main(){
cin >> t;
while(t--){
LL a,k;
cin >> a >> k;
--k;
if(k == 0){
cout << a << endl;
continue;
}
while(1){
LL tmp = solve(a);
--k;
if(!tmp || k == 0){
cout << a+tmp << endl;
break;
}
else a += tmp;
}
}
return 0;
}
B - Young Explorers
题目大意:洛谷上面的一道题.
排个序然后dp.dp[i]表示把当前i到[1,i-a[i]]分成一组时能组成的最大组数.如果暴力的维护的话是O(n2)的.可以用一个f[i]维护1,i里面最大的dp[i]复杂度就降到了O(n).网上的贪心题解可能有些是错的…具体可以看洛谷里的讨论.一大堆贪心里只有一个人是对的…
代码
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#include
using namespace std;
const int N = 2e5+10;
inline int read(){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int a[N],dp[N],f[N];
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
fir(i,1,n) cin >> a[i],dp[i] = 0;
sort(a+1,a+1+n);
int ans = 0;
fir(i,1,n){
if(i >= a[i]){
dp[i] = dp[f[i-a[i]]] + 1;
if(dp[i] > dp[f[i-1]]) f[i] = i;
else f[i] = f[i-1];
}
else dp[i] = 0;
ans = max(ans,dp[i]);
}
cout << ans << endl;
}
return 0;
}
C - Count Triangles
题目大意:给A,B,C,D四个数,x在[A,B],y在[B,C],z在[C,D]问能组成多少个三角形.
因为xyz本身就是有序的.三角形判定定理:最小的两条边和大于第三边.那x+y范围就是[A+B,B+C]里面.这里面每个数的个数可以用差分数组统计.然后问题就变成了[C,D]里面大于C,大于C+1,大于C+2…的数有多少个.前缀和减一下答案就出来了,不过要记得数组开大一点.(开小了RE了一发).
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#include
using namespace std;
const int N = 5e6+10;
inline int read(){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
LL d[N];
int main(){
int A,B,C,D;
LL ans = 0;
cin >> A >> B >> C >> D;
fir(i,A,B){
d[i+B] += 1;
d[i+C+1] -= 1;
}
fir(i,1,N-1) d[i] += d[i-1];
fir(i,1,N-1) d[i] += d[i-1];
fir(i,C,D){
ans += d[B+C] - d[i];
}
cout << ans;
return 0;
}
D - Game With Array
题目大意:能否构造一个长度为N和为S的序列让它的子区间和不等于K或者N-K.S>=K>=0.
cf很喜欢出构造题.想不到的话真的做起来很痛苦.这题还算比较简单的构造.其实问题就是让我们让子区间的值尽量的少.那全部用1去构造就ok了.最后一个数用sum-n+1构造.值域就是1,2…n-1,sum-n+1,sum-n+2…sum.然后看中间有没有空出来的数就可以了.
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#include
using namespace std;
const int N = 1e6+10;
inline int read(){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int ans[N];
int main(){
int n,sum;
cin >> n >> sum;
fir(i,1,n-1){
ans[i] = 1;
}
ans[n] = sum-n+1;
if(ans[n]-n+1 <= 1){
puts("NO");
return 0;
}
puts("YES");
fir(i,1,n) cout << ans[i] << " ";
puts("");
cout << ans[n]-1;
return 0;
}