Codeforces Round #360 (Div. 2) D 数学推导 E dp
Codeforces Round #360 (Div. 2)
A ==
B 水,但记一下:
第 n 个长度为偶数的回文数是 n+reverse(n)。
C dfs 01染色,水
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n, m; struct Edge{int to,next; } e[N<<1]; int tot, head[N], mp[N<<1]; void Addedge(int u, int v) { mp[tot]=tot; e[tot]={v, head[u] }; head[u]=tot++; mp[tot]=tot-1; e[tot]={u, head[v] }; head[v]=tot++; } bool vis[N]; int cnt1, mark[N]; bool dfs(int u, bool flag) { vis[u]=1, mark[u]=flag; if(mark[u]==0) ++cnt1; for(int i=head[u]; i!=-1; i=e[i].next) if(mark[e[i].to]==-1) { bool flag1=dfs(e[i].to, flag^1); if(flag1==false) return false; } else if(mark[e[i].to]==flag) { return false; } return true; } int main() { scanf("%d %d", &n, &m); int u, v; mes(head, -1); mes(mark, -1); rep(i,1,m) { scanf("%d %d", &u, &v); Addedge(u, v); } rep(i,1,n) if(vis[i]==0) { bool flag=dfs(i, 0); if(flag==false) return 0*printf("-1"); } printf("%d\n", cnt1); rep(i,1,n) if(mark[i]==0) printf("%d ", i); puts(""); printf("%d\n", n-cnt1); rep(i,1,n) if(mark[i]==1) printf("%d ", i); puts(""); return 0; }
D 数学推导
题意:给出 k 但不告诉你 x ,并且告诉你 n 个 ci ,你也知道 x%ci, 问 x%k 是否能唯一确定。
tags: 这个题,完全懵的,题目意思都看不懂。。
反过来想,如果 x%k 不能唯一确定,则必定存在 x1、x2 (x1>x2) 满足 x1%ci==x2%ci,且 x1%k != x2%k 。 也就是 (x1-x2)%ci==0,且 (x1-x2)%k != 0 , 进一步说就是: lcm(ci) %(x1-x2)==0 且 lcm(ci)%k != 0 , 也就是 lcm(ci)%k != 0 。 这样就得出命题: 如果 x%k 不能唯一确定,那么 lcm(ci)%k != 0。 变为逆否命题即:如果 lcm(ci)%k==0 ,那么 x%k 能唯一确定。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 1000005; ll n, k, c[N]; int main() { scanf("%lld %lld", &n, &k); ll lcm1=1; rep(i,1,n) { scanf("%lld", &c[i]); if(lcm1) ( lcm1 = c[i]*lcm1/__gcd(c[i], lcm1) ) %=k; else break; } if(lcm1%k==0) puts("Yes"); else puts("No"); return 0; }
E 三维dp
题意: 给你一些硬币,让你选出一个子集的总价值和为 k,然后对于一个选出的子集,除了可以组成k以外,还可以在选出的子集中选出一些其他的价值。问你所有的选出的子集一共可以得到多少种价值。
tags: CF 评测机我是服气的,1.25e8 两秒的时限,这都能过。。
dp[i][j][k] 表示前 i 个硬币,当前遍历到第 i 个硬币时,选出的集合的总和是 j ,子集合的和是 k 的方案数。 递推式: dp[i][j][k] = dp[i-1][j]+dp[i-1][j-ci][k]+dp[i-1][j-ci][k-ci] 。(即遍历到第 i 个硬币时,可以不选它,也可以选它加入到总集合,但不加入子集合, 也可选它加入到两个集合)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 501; int n, ki, c[N]; ll dp[2][N][N]; int main() { scanf("%d %d", &n, &ki); rep(i,1,n) scanf("%d", &c[i]); int cnt=0; dp[cnt^1][0][0] = 1; rep(i,1,n) { rep(j,0,ki) rep(k,0,j) { dp[cnt][j][k]=0; dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j][k]); if(j-c[i]>=0) dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j-c[i]][k]); if(k-c[i]>=0) dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j-c[i]][k-c[i]]); } cnt ^= 1; } cnt ^= 1; int ans=0; rep(k,0,ki) if(dp[cnt][ki][k]) ++ans; printf("%d\n", ans); rep(k,0,ki) if(dp[cnt][ki][k]) printf("%d ", k); puts(""); return 0; }