日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

codeforces:1361(div1)1362(div2):总结

發(fā)布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 codeforces:1361(div1)1362(div2):总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 1362-A. Johnny and Ancient Computer
    • 解析
  • 1362-B - Johnny and His Hobbies
    • 解析
  • 1362-C - Johnny and Another Rating Drop
    • 解析
  • 1361-A Johnny and Contribution
    • 解析
  • 1361-B - Johnny and Grandmaster
    • 解析
  • 1361-C - Johnny and Megan's Necklace
    • 解析
  • 1361-D - Johnny and James
    • 解析

前言

比昨天的題惡心億點點
最后D題死活調(diào)不出來了整了兩個半小時
qwq

1362-A. Johnny and Ancient Computer

給定 a,b,你可以把 aaa 的值設(shè)為以下幾種之一:
a?2
a?4
a?8
a÷2(如果它被 2 整除)
a÷4(如果它被 4 整除)
a÷8(如果它被 8 整除)
求出至少需要幾次操作才能把 a 變成 b。如果無解,輸出 -1,表示這是不可能的。
多組數(shù)據(jù),數(shù)據(jù)組數(shù) t≤1000,1≤a,b≤1018t\leq 1000 ,1 \leq a,b\leq 10^{18}t1000,1a,b1018

解析

大水題
判斷整除、除完一的個數(shù)后暴力數(shù)需要移動幾位即可

#include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e5+100; const int mod=998244353; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m,q; int calc(ll x){return x?calc(x>>1)+1:0;} signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifint T=read();while(T--){ll a=read(),b=read();if(a<b) swap(a,b);if(a%b) printf("-1\n");else{ll o=a/b;if(o!=(o&-o)) printf("-1\n");else printf("%d\n",(calc(o)+1)/3);}}return 0; }

1362-B - Johnny and His Hobbies

有一個大小為 n 的集合 S={s1,s2,...,sn}S=\{s_1,s_2,...,s_n\}S={s1?,s2?,...,sn?}。你需要求出一個最小的正整數(shù) k,使得 {s1⊕k,s2⊕k,...,sn⊕k}=S\{s_1 \oplus k,s_2 \oplus k,...,s_n \oplus k\}=S{s1?k,s2?k,...,sn?k}=S。
如果不存在這樣的 k,輸出 ?1。
t≤1024,1≤n≤1024,∑n≤1024,0≤si<1024t \leq 1024,1 \leq n \leq 1024,\sum n \leq 1024,0 \leq s_i < 1024t1024,1n1024,n1024,0si?<1024

解析

注意到數(shù)據(jù)范圍很小,n方可以通過
暴力枚舉aia_iai?映射的值判斷合法再取最小即可

#include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const int mod=998244353; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m,q; int a[N],bac[N]; signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifint T=read();while(T--){int res=1e9;n=read();memset(bac,0,sizeof(bac));for(int i=1;i<=n;i++) a[i]=read(),bac[a[i]]=1;for(int i=2;i<=n;i++){int o=a[1]^a[i],flag=1;for(int j=1;j<=n;j++){if(bac[a[j]^o]==0){flag=0;break;}}if(flag) res=min(res,o);}printf("%d\n",res<1e9?res:-1);}return 0; }

1362-C - Johnny and Another Rating Drop

定義兩個數(shù)的差異為它們在二進(jìn)制下不同的位的數(shù)量(我們認(rèn)為它們補(bǔ)充了足夠的前導(dǎo)零)。
例如,0101 和 1110 的差異為 3
你需要求出 0,1,2,..,n?1,n0,1,2,..,n-1,n0,1,2,..,n?1,n 中相鄰的數(shù)的差異之和。
t≤10000t \leq 10000t100001≤n≤10181 \leq n \leq 10^{18}1n1018

解析

如果你沒什么思路,給你看看他的樣例:

n=5:
000
001
010
011
100
101

謎底寫在謎面上
按位考慮即可

#include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const int mod=998244353; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m,q; ll mi[100]; signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifint T=read();mi[0]=1;for(int i=1;mi[i-1]<=1e18;i++) mi[i]=mi[i-1]<<1;while(T--){ll a=read(),res(0);for(int i=0;mi[i]<=a;i++){res+=(a+1+mi[i]-1)/mi[i]-1;}printf("%lld\n",res);}return 0; }

1361-A Johnny and Contribution

給定 n 個點 m 條邊的無向圖。第 i 點被要求標(biāo)上一個大小在 [1,n] 之間的正整數(shù) tit_iti??。
在實際標(biāo)數(shù)的過程中,操作者會按照一個特定的順序 p1,p2,...,pnp_1,p_2,...,p_np1?,p2?,...,pn? 來標(biāo)數(shù)。
當(dāng)給一個點 x 標(biāo)數(shù)的時候,操作者會找到一個(最小的,在已經(jīng)被標(biāo)上數(shù)且與 x 相連的點中沒有出現(xiàn)過的,)正整數(shù) v,并把點 x 標(biāo)上 v。
你需要求出 p1,p2,...,pnp_1,p_2,...,p_np1?,p2?,...,pn??,這樣操作者標(biāo)數(shù)之后,第 iii 個點會被標(biāo)上 ti?t_i?ti??。
1≤n,m≤5?105,1≤ti≤n1 \leq n,m \leq 5\cdot 10^5,1 \leq t_i \leq n1n,m5?105,1ti?n 無重邊無自環(huán)

解析

直接從小到大考慮標(biāo)記點,標(biāo)記完把與它相連的打個標(biāo)記即可
如果該點在自己的第k輪被打了標(biāo)記或者之前打的標(biāo)記次數(shù)少于k-1,就是無解
實現(xiàn)用時間戳標(biāo)記,具體見代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=5e5+100; const int mod=998244353; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m; struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt;return; } vector<int>v[N]; int du[N],tim,tag[N]; int ans[N],tot; signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read();addline(x,y);addline(y,x);}for(int i=1;i<=n;i++){v[read()].push_back(i);}for(tim=1;tim<=n;tim++){for(int i=0,o=v[tim].size();i<o;i++){int x=v[tim][i];if(tag[x]==tim||du[x]<tim-1){printf("-1\n");return 0;}ans[++tot]=x;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(tag[to]!=tim){tag[to]=tim;du[to]++;}}}}for(int i=1;i<=tot;i++) printf("%d ",ans[i]);return 0; }

1361-B - Johnny and Grandmaster

給定 n,p 和 n 個形如 pkip^{k_i}pki?的整數(shù)?,要求將這 n 個數(shù)分為兩個集合,最小化兩個集合的各自的和的差的絕對值,答案對 109+710^9+7109+7 取模。
∑n≤106,1≤p≤106,0≤ki≤106\sum n\le 10^6,1\le p\le 10^6,0\le k_i\le 10^6n106,1p106,0ki?106

解析

不太難但挺有意思的貪心題
貪心策略:

從高到低位取,每次都盡可能最小化當(dāng)前的差值

證明:
假設(shè)當(dāng)前在第k位,沒有最小化當(dāng)前的差值
那么當(dāng)前差值會增大 2?pk2*p^k2?pk
設(shè)[0,k-1]位的和為sumsumsum

  • sum≥2?pksum\geq 2*p^ksum2?pk,那么顯然后面需要把這個差值先補(bǔ)上來,那么我們不如不要這個差值,讓補(bǔ)上來的兩個pkp^kpk互相抵消,這樣是不劣的
  • sum≤2?pksum\leq 2*p^ksum2?pk,那么答案就會至少是pk?1p^{k-1}pk?1,但是不難看出,如果不要這個差值,不難發(fā)現(xiàn)答案不會超過pk?1p^{k-1}pk?1,所以是不優(yōu)秀的
  • 比較感性,但湊和看吧
    后面的實現(xiàn)就不是很難了
    主要你別和我一樣傘兵換底公式倒錯就行

    #include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m; ll p; int tag[N],tim,num[N]; vector<int> v; inline void add(int id){if(tag[id]!=tim){tag[id]=tim;v.push_back(id);num[id]=1;}else num[id]++;return; } inline ll ksm(ll x,ll k){ll res(1);while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res; } ll calc(int k){ll res(0);for(int i=k;i>=0;i--) (res+=num[v[i]]*ksm(p,v[i]))%=mod;return res; } signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifint T=read();for(tim=1;tim<=T;tim++){v.clear();v.shrink_to_fit(); n=read();p=read();for(int i=1;i<=n;i++){int o=read();add(o);}sort(v.begin(),v.end());ll cnt(0);int flag(0);for(int i=v.size()-1;i>=0;i--){int x=v[i];if(num[x]>=cnt){num[x]-=cnt;cnt=num[x]&1;}else cnt-=num[x];if(i>0&&cnt){int d=v[i]-v[i-1];if(1.0*(log(n)-log(cnt))/log(p)<d){flag=1;printf("%lld\n",(cnt%mod*ksm(p,x)-calc(i-1)+mod)%mod);break;}else cnt*=ksm(p,d);}}if(!flag)printf("%lld\n",cnt%mod*ksm(p,v[0])%mod);}return 0; }

    1361-C - Johnny and Megan’s Necklace

    n 對珍珠由 n 條線所連起來,共 2n 顆?,F(xiàn)在你可以在任意兩個未被線連起來的珍珠之間連一條線,共可連 n 條,使得這 2n 顆珍珠形成一個環(huán)。
    設(shè)一條線所連的兩顆珍珠權(quán)值為 u,v,則該線的權(quán)值為最大的整數(shù) k 滿足 2k∣uxor?v2^k∣u \operatorname{xor} v2kuxorv 。如果 u=v,則 k=20。
    求所有新連的線的權(quán)值最小值的最大值并給出方案,即 2n 顆珍珠所形成的的環(huán)。

    解析

    關(guān)于最值,不難想到二分答案
    對于一個給定的答案k,兩顆珍珠可以連接當(dāng)且僅當(dāng)二者的[0,k-1]位完全相同
    考慮把每一個長度為k的后綴建一個點,每顆珍珠向自己的伴侶和自己的后綴連一條邊
    然后跑歐拉回路即可

    #include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=3e6+100; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m;struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){//printf(" addline:%d->%d\n",x,y);p[++cnt]=(node){y,fi[x]};fi[x]=cnt;return; }int a[N],b[N]; int zhan[N],top; bool jd[N]; int du[N]; void dfs(int x){//printf("dfs:%d\n",x);for(int i=fi[x];~i;i=fi[x]){int to=p[i].to;fi[x]=p[i].nxt;jd[i^1]=1;if(!jd[i]){//printf("%d->%d\n",x,to);dfs(to);}}zhan[++top]=x; } bool check(int k){int s=(1<<k)-1;memset(fi,-1,sizeof(fi));cnt=-1;memset(jd,0,sizeof(jd));memset(du,0,sizeof(du));for(int i=1;i<=n;i++){addline(2*i-1,2*i);addline(2*i,2*i-1);}int mx(0);for(int i=1;i<=n;i++){int x=a[i]&s,y=b[i]&s;++x;++y;//printf("\ni=%d x=%d y=%d\n",i,x,y);addline(2*i-1,2*n+x);addline(2*n+x,2*i-1);addline(2*i,2*n+y);addline(2*n+y,2*i);du[2*n+x]++;du[2*n+y]++;mx=max(mx,max(x,y));}for(int i=1;i<=mx;i++){if(du[i+2*n]&1) return false;}top=0;dfs(1);return top==3*n+1; } int main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();for(int i=1;i<=n;i++){a[i]=read();b[i]=read();}//printf("%d\n",check(3));//while(top) printf("%d ",zhan[top--]);//return 0;int st=0,ed=20;while(st<ed){int mid=(st+ed+1)>>1;if(check(mid)) st=mid;else ed=mid-1;}check(st);printf("%d\n",st);--top;while(top){if(zhan[top]<=2*n) printf("%d ",zhan[top]);--top;}return 0; }

    1361-D - Johnny and James

    平面上給定 n 個互不相同的點,其中一個點是原點
    建一棵樹,原點為根,一個不為原點的點的父親為其到原點的線段上的第二個點,邊長即為到父親的歐幾里得距離
    求選出 k 個不同的點,這些點兩兩距離和最大值
    2≤k≤n≤5×1052 \le k \le n \le 5 \times 10^52kn5×105

    解析

    大毒瘤題…
    是好幾種方法都假掉了,又寫了一堆bug
    qwq
    思路也不太好想

    如果我們知道一條鏈上取的點的個數(shù),我們應(yīng)該取那些點呢?
    對于前k/2個,由于鏈外的點更多,我們應(yīng)該從下往上取,而對于超過k/2個,由于下方的點更多,我們應(yīng)該從上往下取

    所以我們可以分開來考慮增量
    (設(shè) x 到根的距離為 disxdis_xdisx?
    對于從下往上取的前k/2個:設(shè)其為從下往上第 i 個,那么它會往根連接 k?ik-ik?i 條邊,產(chǎn)生(k?i)×disi(k-i) \times dis_i(k?i)×disi? 的貢獻(xiàn);同時,由于下方的所有點計算到i的路徑時,本來是連向根的,現(xiàn)在變成連向 i ,因此又將付出 (i?1)×disi(i-1) \times dis_i(i?1)×disi?的代價。總的價值就是 (k?i?(i?1))×disi(k-i -(i-1)) \times dis_i(k?i?(i?1))×disi?

    對于從上往下取的前k/2個:設(shè)其為從上往下第 i 個,那么它會往根連 k?k/2?(i?1)k-k/2-(i-1)k?k/2?(i?1)條邊(k/2是第一種情況的點),產(chǎn)生 (k?i)×disi(k-i) \times dis_i(k?i)×disi?的貢獻(xiàn);對于下方的點,和第一種情況類似的,也要付出(k/2)×disi(k/2) \times dis_i(k/2)×disi?;同時,它的祖先們往i連邊本來是當(dāng)成向根連邊計算的,但現(xiàn)在變成了連向 i 變化值是∑u∈ancestoridisi?disu?disu\sum_{u\in ancestor_i}dis_i-dis_u-dis_uuancestori??disi??disu??disu?。因此,總的價值就是:(k?k/2?k/2+i?1)×disi?2×∑u∈ancestoridisu(k-k/2-k/2+i-1) \times dis_i-2 \times \sum_{u\in ancestor_i}dis_u(k?k/2?k/2+i?1)×disi??2×uancestori??disu?

    算出選取每個點的貢獻(xiàn),sort一下后取前k個即可

    #include<bits/stdc++.h> using namespace std; #define ll long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=5e5+100; const int mod=1e9+7; const double eps=1e-9; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }ll gcd(ll x,ll y){ return y?gcd(y,x%y):x;}int n,m; int rt; map<int,map<int,int>>mp; int bel[N],tot; vector<int> v[N]; ll x[N],y[N]; double dep[N]; struct node{int to,nxt;double w; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y,double w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;return; }bool cmp(int x,int y){return dep[x]>dep[y];} bool vis[N]; double q[N]; int num; int main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=n;i++){x[i]=read();y[i]=read();if(!x[i]&&!y[i]){rt=i;continue;}dep[i]=sqrt(x[i]*x[i]+y[i]*y[i]);int g=gcd(abs(x[i]),abs(y[i])),a=abs(x[i])/g,b=abs(y[i])/g;if(x[i]<0){//printf("ok a=%d\n",a);a=-a;}if(y[i]<0) b=-b;if(!x[i]) a=0,b=y[i]>0?1:-1;if(!y[i]) b=0,a=x[i]>0?1:-1;if(!mp[a][b]) mp[a][b]=++tot;int o=mp[a][b];bel[i]=o;v[o].push_back(i);//printf("i=%d bel=%d dep=%lf g=%d a=%d b=%d x[i]=%lld y[i]=%lld\n",i,bel[i],dep[i],g,a,b,x[i],y[i]);}v[++tot].push_back(rt);num=0;for(int o=1;o<=tot;o++){//printf("o=%d\n\n",o);int ww=v[o].size();sort(v[o].begin(),v[o].end(),cmp);for(int i=0;i<min(ww,m/2);i++){int x=v[o][i];q[++num]=(m-2*i-1)*dep[x];//printf("down:x=%d dep=%lf add=%lf\n",x,dep[x],(m-2*i-1)*dep[x]);}double sum(0);for(int i=ww-1;i>=m/2;i--){int x=v[o][i];q[++num]=(m-2*(m/2)-1)*dep[x]-2*sum;//printf("up:x=%d dep=%lf add=%lf\n",x,dep[x],(m-2*(m/2)-1)*dep[x]-2*sum);sum+=dep[x];}}double ans(0);sort(q+1,q+1+num);//for(int i=1;i<=num;i++) printf("%lf\n",q[i]);for(int i=num;m;i--,m--) ans+=q[i];printf("%.8lf\n",ans);return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的codeforces:1361(div1)1362(div2):总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。