[CF]Avito Cool Challenge 2018
A(簽到)
題意:簽到
00:01 1A
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)
const int N = 1e5+7;
const int MX = 1e9+7;
const LL INF = 1e18+9LL;
int main(){
int x;
cin>>x;
if(x==2)cout<<2;
else cout<<1;
}
View Code
B(構(gòu)造)
題意:有長度為n的數(shù)列B,Ai表示B中與Bi不同的值的數(shù)量,給出數(shù)列A,求B
顯然
1若Ai不同則Bi一定不同
2一定有n-Ai個數(shù)等于Bi
推出相同Ai的個數(shù)一定是n-Ai的倍數(shù),其中每組n-Ai個Bi相等,否則無解,有解時方案按之前推論構(gòu)造即可。
這題開始還沒想出來,不應(yīng)該。。
01:12 2A
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)
const int N = 1e5+7;
const int MX = 1e9+7;
const LL INF = 1e18+9LL;
int a[N],sum[N],ans[N],lim[N];
vector<int> b[N];
int main(){
int n;
cin>>n;
rep(i,n){
scanf("%d",&a[i]);
b[a[i]].pb(i);
sum[a[i]]++;
}
for(int i=0;i<n;i++){
if(sum[i]%(n-i)){
cout<<"Impossible";
return 0;
}
lim[i]=n-i;
}
cout<<"Possible"<<endl;
int cnt=1;
for(int i=0;i<n;i++){
for(int j=0;j<b[i].size();j++){
ans[b[i][j]]=cnt;
if((j+1)%lim[i]==0)cnt++;
}
}
rep(i,n)cout<<ans[i]<<" ";
return 0;
}
View Code
C(dp)
題意:給n個方格涂m種顏色,有k個方格和左邊的方格顏色不同,求方案數(shù)。(n<=2000,m<=2000)
f[i][j]=f[i-1][j]+(m-1)*f[i-1][j-1],輸出f[n][k]即可。數(shù)組可以滾動,但沒必要。O(nk)
或者直接推公式也不難
00:23 1A
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)
const int N = 2e3+7;
const int MX = 1e9+7;
const LL INF = 1e18+9LL;
const LL mod=998244353;
LL dp[N][N];
int main(){
int n,m,k;
cin>>n>>m>>k;
dp[0][0]=1;
rep(i,n)
for(int j=0;j<i&&j<=k;j++){
if(j==0){
dp[i][j]=m;
continue;}
dp[i][j]=((dp[i-1][j-1]*(m-1))%mod+dp[i-1][j])%mod;
}
cout<<dp[n][k];
}
View Code
D(MST)
題意:給出一個加權(quán)無向圖,有k個特殊結(jié)點(diǎn)。定義路徑長度為路徑上的最大邊權(quán),求這k個結(jié)點(diǎn)到其他特殊結(jié)點(diǎn)最短路的最大值。
定義開始看起來很繞,后來一想其實類似貨車運(yùn)輸。首先最短路一定在最小生成樹上取到,觀察樣例可以猜想所有最大值相等。事實上,考慮kruskal算法過程,當(dāng)一條邊被加入時,如果他兩邊的并查集都含有特殊結(jié)點(diǎn),那么答案一定不比這條邊小,因為樹上的路徑唯一,兩邊的特殊結(jié)點(diǎn)間的路徑一定包含這條邊,據(jù)此也可發(fā)現(xiàn)所有結(jié)點(diǎn)的答案一定都相等。所以只需在kruskal執(zhí)行時維護(hù)每個并查集的大小,當(dāng)加入一條邊后有一個并查集大小為k時,說明所有特殊結(jié)點(diǎn)已經(jīng)聯(lián)通,之后的邊都不會影響答案,而當(dāng)前加入的這條邊一定連接了兩個特殊結(jié)點(diǎn),所以這條邊的權(quán)值就是所有特殊結(jié)點(diǎn)的最大值。
比賽的時候沒時間做了,想到了最小生成樹,開始猜想最大值相等但是之后又想錯了,主要還是開始理解題意耽誤太多時間了。
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)
const int N=1e5+7;
struct st
{
int u,v,w;
}edge[N];
int f[N],ans[N],is[N],sz[N];
int n,m,k;
int cmp(st a,st b){
return a.w<b.w;
}
int finde(int x)
{
if(x!=f[x])
f[x]=finde(f[x]);
return f[x];
}
int make(int a,int b)
{
int x=finde(a);
int y=finde(b);
f[x]=y;
sz[y]+=sz[x];
return sz[y]==k;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
rep(i,k){
int x;
scanf("%d",&x);
is[x]=1;
}
rep(i,m)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[i].u=a;
edge[i].v=b;
edge[i].w=c;
}
for(int i=1;i<=n;i++) {
f[i]=i;
if(is[i])sz[i]=1;
}
sort(edge+1,edge+m+1,cmp);
rep(i,m)
{
int u=edge[i].u;
int v=edge[i].v;
if(finde(u)!=finde(v))
{
if(make(u,v)){
rep(j,k)cout<<edge[i].w<<" ";
return 0;
}
}
}
return 0;
}
View Code
E(數(shù)學(xué),構(gòu)造)
題意:長度為n(n為偶數(shù))的數(shù)列A的任意項前綴和為完全平方數(shù),給出所有偶數(shù)項,求數(shù)列A,若有解保證存在1e13之內(nèi)的解。(n<=1e5,Ai<=2e5)
令Bi為A的前i項和,令B2*i=p^2,B2*I-1=q^2,則A2*i=p^2-q^2=(q+p)*(p-q),顯然p-q<sqrt(Ai),因此枚舉p-q的值,即可解出p和q。因為要保證B遞增,所以要取使p最小的可行解,這樣
之后的選擇空間更大。O(n*sqrt(Ai))
02:19 3A
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)
const int N = 1e5+7;
const int MX = 1e9+7;
const LL INF = 1e18+9LL;
LL ans[N],a[N];
int main(){
int n;
cin>>n;
int cnt=0;
rep(i,n/2){
LL x;
cin>>x;
a[i*2]=x;
LL j;
for(j=sqrt(x);j>=1;j--){
if(j*j==x)j--;
if(!j)break;
if(x%j==0&&(x/j-j)%2==0&&(x/j-j)/2>ans[cnt]){
ans[++cnt]=(x/j-j)/2;
ans[++cnt]=(x/j+j)/2;
break;
}
}
if(j==0){
cout<<"No";
return 0;
}
}
cout<<"Yes"<<endl;
LL now=0;
for(int i=1;i<n;i+=2){
cout<<ans[i]*ans[i]-now<<" "<<a[i+1]<<" ";
now=ans[i+1]*ans[i+1];
}
}
View Code
標(biāo)答是O(Ai*log(Ai))的,還沒仔細(xì)看,先貼這里。
Let,xmax?=?2?×?105.
Sincex2i?=?s2i?-?s2i?-?1?=?t2i2?-?t2i?-?12?≥?(t2i?-?1?+?1)2?-?t2i?-?12?=?2t2i?-?1?+?1, so2t2i?-?1?+?1?≤?xmax,t2i?-?1?<?xmax.
For every, we can precalculate all possible(a,?b)s so thatx?=?b2?-?a2: enumerate all possiblea, then for everyaenumeratebfrom small to large starting froma?+?1and stop whenb2?-?a2?>?xmax, record this(a,?b)forx?=?b2?-?a2. Since, then, its complexity is.
Now, we can try to find a possiblesfrom left to right. Sincex2i?-?1is positive, we need to ensuret2i?-?2?<?t2i?-?1. Becuasex2i?=?t2i2?-?t2i?-?12, we can try all precalculated(a,?b)s such thatx2i?=?b2?-?a2. If we have several choices, we should choose the one thatais minimum possible, because if the current sum is bigger, it will be harder for the remaining number to keep positive.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n;
ll sq[100099];
#define S 200000
vector<pii> v[S+55];
int main()
{
for(int i=1;i<=S;++i)
{
if(i*2+1>S) break;
for(int j=i+1;j*(ll)j-i*(ll)i<=S;++j)
v[j*(ll)j-i*(ll)i].push_back(pii(i,j));
}
scanf("%d",&n);
for(int i=2;i<=n;i+=2)
{
int x; scanf("%d",&x);
for(auto t:v[x])
if(sq[i-2]<t.first)
{
sq[i-1]=t.first,sq[i]=t.second;
break;
}
if(!sq[i-1])
{puts("No"); return 0;}
}
puts("Yes");
for(int i=1;i<=n;++i)
printf("%lld%c",sq[i]*(ll)sq[i]-sq[i-1]
*(ll)sq[i-1],"
"[i==n]);
}
View Code
總結(jié)
以上是生活随笔為你收集整理的[CF]Avito Cool Challenge 2018的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用 tf object detec
- 下一篇: Navicat安装激活