Codeforces Round #534 Div. 1
A:用一列放竖着的方块,两列放横着的方块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 1010 char getc (){ char c= getchar (); while ((c< 'A' ||c> 'Z' )&&(c< 'a' ||c> 'z' )&&(c< '0' ||c> '9' )) c= getchar (); return c;} int gcd( int n, int m){ return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1; char c= getchar (); while (c< '0' ||c> '9' ) { if (c== '-' ) f=-1;c= getchar ();} while (c>= '0' &&c<= '9' ) x=(x<<1)+(x<<3)+(c^48),c= getchar (); return x*f; } int n; char s[N]; signed main() { #ifndef ONLINE_JUDGE freopen ( "a.in" , "r" ,stdin); freopen ( "a.out" , "w" ,stdout); #endif scanf ( "%s" ,s+1);n= strlen (s+1); int x=0,y=0; for ( int i=1;i<=n;i++) if (s[i]== '0' ) { x++; if (x&1) cout<<1<< ' ' <<1<<endl; else cout<<3<< ' ' <<1<<endl; } else { y++; if (y>4) y=1; cout<<y<< ' ' <<2<<endl; } return 0; //NOTICE LONG LONG!!!!! } |
B:先询问2k 2k+1,假设已经知道了a>2k,则当a>2k+1时,后者大,否则前者大。这样可以倍增出一个a的取值区间。注意到在区间内x mod a值开始单增,中间突变为0(即x=a),然后又单增,并且最开始的值要比最终的值大。于是拿2k+1和一个二分值比较即可。注意特判a=1的情况,询问0和1即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long char getc (){ char c= getchar (); while ((c< 'A' ||c> 'Z' )&&(c< 'a' ||c> 'z' )&&(c< '0' ||c> '9' )) c= getchar (); return c;} int gcd( int n, int m){ return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1; char c= getchar (); while (c< '0' ||c> '9' ) { if (c== '-' ) f=-1;c= getchar ();} while (c>= '0' &&c<= '9' ) x=(x<<1)+(x<<3)+(c^48),c= getchar (); return x*f; } char s[10]; signed main() { cin>>(s+1); while (s[1]!= 'e' ) { cout<< '?' << ' ' <<0<< ' ' <<1<<endl; char c;cin>>c; if (c== 'x' ) cout<< '!' << ' ' <<1<<endl; else { int x; for ( int i=0;i<30;i++) { cout<< '?' << ' ' <<(1<<i)<< ' ' <<(1<<i+1)<<endl; cin>>c; if (c== 'x' ) {x=i; break ;} } int y=(1<<x+1); int l=(1<<x)+1,r=y-1,ans=y; while (l<=r) { int mid=l+r>>1; cout<< '?' << ' ' <<mid<< ' ' <<y<<endl; cin>>c; if (c== 'x' ) l=mid+1; else ans=mid,r=mid-1; } cout<< '!' << ' ' <<ans<<endl; } cin>>(s+1); } return 0; //NOTICE LONG LONG!!!!! } |
C:二选一当然是考虑问题间有什么关系。随便找一棵dfs树,如果深度>=n/k,那么显然有一条长度为n/k的简单路径;否则由抽屉原理,至少有一层的点数超过k,由此可得树的叶子数量超过k。注意到由于每个点度数至少为3,叶子至少会往上连两条边。我们考虑对每个叶子构造一个以其为标记的环。唯一的要求是环长不能为3的倍数,由于我们有至少两条边,所以可以得到至少三个包含该叶子的环,容易发现其中一定存在一个满足要求的。并且由于环长不会超过树的深度,所以总输出量也是O(n)的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> #include<cassert> using namespace std; #define ll long long #define N 500010 char getc (){ char c= getchar (); while ((c< 'A' ||c> 'Z' )&&(c< 'a' ||c> 'z' )&&(c< '0' ||c> '9' )) c= getchar (); return c;} int gcd( int n, int m){ return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1; char c= getchar (); while (c< '0' ||c> '9' ) { if (c== '-' ) f=-1;c= getchar ();} while (c>= '0' &&c<= '9' ) x=(x<<1)+(x<<3)+(c^48),c= getchar (); return x*f; } int n,m,k,p[N],deep[N],fa[N],t,root=1; bool flag[N],isleaf[N]; struct data{ int to,nxt; }edge[N<<1]; void addedge( int x, int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void dfs( int k) { flag[k]=1; int son=0; for ( int i=p[k];i;i=edge[i].nxt) if (!flag[edge[i].to]) { deep[edge[i].to]=deep[k]+1; fa[edge[i].to]=k; son++; dfs(edge[i].to); } if (son==0) isleaf[k]=1; } signed main() { #ifndef ONLINE_JUDGE freopen ( "c.in" , "r" ,stdin); freopen ( "c.out" , "w" ,stdout); #endif n=read(),m=read(),k=read(); for ( int i=1;i<=m;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); } deep[root]=1;dfs(root); for ( int i=1;i<=n;i++) if (deep[i]>=n/k+(n%k>0)) { cout<< "PATH" <<endl;cout<<deep[i]<<endl; for ( int x=i;x!=root;x=fa[x]) printf ( "%d " ,x); cout<<root; return 0; } cout<< "CYCLES" <<endl; for ( int i=1;i<=n;i++) if (isleaf[i]) { bool f=0; for ( int j=p[i];j;j=edge[j].nxt) if (edge[j].to!=fa[i]&&(deep[i]-deep[edge[j].to])%3!=2) { printf ( "%d\n" ,deep[i]-deep[edge[j].to]+1); for ( int x=i;x!=edge[j].to;x=fa[x]) printf ( "%d " ,x); printf ( "%d\n" ,edge[j].to); f=1; break ; } if (!f) { int u=0,v=0; for ( int j=p[i];j;j=edge[j].nxt) if (edge[j].to!=fa[i]) if (!u) u=edge[j].to; else if (!v) v=edge[j].to; else break ; if (deep[u]<deep[v]) swap(u,v); printf ( "%d\n" ,deep[u]-deep[v]+2); printf ( "%d " ,i); while (u!=v) printf ( "%d " ,u),u=fa[u]; printf ( "%d\n" ,v); } k--; if (k==0) break ; } return 0; //NOTICE LONG LONG!!!!! } |
D:先求出所有数的gcd,显然每次对一个数操作都应该去除gcd至少一种质因子,给每个数只保留这些质因子。由于值域1e12,不同的质因子数量最多为11个,设该数为m,那么所需要操作的数也不会超过m个。显然可以得到一个dp,即f[i][j][k]为前i个数操作j个质因子状态为k的最小Σe。复杂度O(n·m·3m)。
注意到对于这m种质因子次数均相同的数,只需要保留代价最小的m个。于是先去一下重,猜想去重之后剩下数的数量就不会特别多。但乘上m·3m后还是跑不动。进一步发现对于均能去除某一质因子集合的数,也只需要保留代价最小的m个。这样继续暴力去重,剩下数的数量不超过m·2m,并且同时我们可以求出每个数可以用于去除哪些集合,总集合数量是m·2m的。回到原dp中可以发现复杂度就变成了O(m2·3m)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; #define ll long long #define N 1000010 #define M 11 char getc (){ char c= getchar (); while ((c< 'A' ||c> 'Z' )&&(c< 'a' ||c> 'z' )&&(c< '0' ||c> '9' )) c= getchar (); return c;} ll gcd(ll n,ll m){ return m==0?n:gcd(m,n%m);} ll read() { ll x=0,f=1; char c= getchar (); while (c< '0' ||c> '9' ) { if (c== '-' ) f=-1;c= getchar ();} while (c>= '0' &&c<= '9' ) x=(x<<1)+(x<<3)+(c^48),c= getchar (); return x*f; } int n,cnt[M],t,LG2[1<<M]; ll m,k,p[M],pw[M][100],tot[1<<M],f[M][1<<M]; bool flag[N]; struct data { int v;ll x; bool operator <( const data&a) const { return x<a.x; } }a[N],b[N]; vector< int > s[N]; priority_queue<data> q[1<<M]; bool cmp( const data&a, const data&b) { return a.v<b.v; } signed main() { #ifndef ONLINE_JUDGE freopen ( "d.in" , "r" ,stdin); freopen ( "d.out" , "w" ,stdout); #endif n=read(),k=read(); for ( int i=1;i<=n;i++) m=gcd(m,a[i].x=read()); for ( int i=1;i<=n;i++) a[i].v=read(); for (ll i=2;i*i<=m;i++) if (m%i==0) { p[t++]=i; while (m%i==0) m/=i; } if (m>1) p[t++]=m; if (t==0) {cout<<0; return 0;} for ( int i=0;i<t;i++) { pw[i][0]=1; for ( int j=1;j<100;j++) pw[i][j]=pw[i][j-1]*p[i]; } sort(a+1,a+n+1); int u=0; for ( int i=1;i<=n;i++) { int v=i; while (a[v+1].x==a[i].x) v++; sort(a+i,a+v+1,cmp); for ( int j=1;j<=min(t,v-i+1);j++) b[++u]=a[i+j-1]; i=v; } swap(a,b);n=u; for ( int i=0;i<M;i++) LG2[1<<i]=i; for ( int j=1;j<(1<<t);j++) for ( int i=0;i<t;i++) q[j].push((data){0,100000000000000ll}); for ( int i=1;i<=n;i++) { tot[0]=1; ll u=a[i].x; memset (cnt,0, sizeof (cnt)); for ( int j=0;j<t;j++) while (u%p[j]==0) cnt[j]++,u/=p[j]; for ( int j=1;j<(1<<t);j++) { tot[j]=tot[j^(j&-j)]*pw[LG2[j&-j]][cnt[LG2[j&-j]]]; if (tot[j]<=k&&a[i].v<q[j].top().x) q[j].pop(),q[j].push((data){i,a[i].v}); } } for ( int j=1;j<(1<<t);j++) while (!q[j].empty()) { data x=q[j].top();q[j].pop(); s[x.v].push_back(j); } memset (f,42, sizeof (f));f[0][0]=0; for ( int i=1;i<=n;i++) for ( int j=t-1;j>=0;j--) { for ( int k=0;k<s[i].size();k++) { int x=s[i][k]; f[j+1][x]=min(f[j+1][x],f[j][0]+a[i].v); for ( int y=(1<<t)-1^x;y;y=y-1&((1<<t)-1^x)) f[j+1][x|y]=min(f[j+1][x|y],f[j][y]+a[i].v); } } ll ans=1000000000000000ll; for ( int i=1;i<=t;i++) if (f[i][(1<<t)-1]<ans) ans=min(ans,i*f[i][(1<<t)-1]); if (ans>=1000000000000000ll) cout<<-1; else cout<<ans; return 0; //NOTICE LONG LONG!!!!! } |
E感觉过于神仙。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· 支付宝事故这事儿,凭什么又是程序员背锅?有没有可能是这样的...
· 在线客服系统 QPS 突破 240/秒,连接数突破 4000,日请求数接近1000万次,.NET 多
· C# 开发工具Visual Studio 介绍
· 在 Windows 10 上实现免密码 SSH 登录
· C#中如何使用异步编程