A
题意
给出一个长度为的序列 。选出他的一个子序列。满足下列条件。
- 必须选择
- 对于所有的(为所选序列的长度)都有
输出一个符合条件的子序列。
solve
将所有满足的都选上。如果无法达到条件3,说明无解。否则输出。
code
/* * @Author: wxyww * @Date: 2019-07-20 23:34:52 * @Last Modified time: 2019-07-21 07:52:08 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int N = 110; 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*10+c-'0'; c=getchar(); } return x*f; } int SUM,a[N],bz[N],num; int main() { int n = read(); for(int i = 1;i <= n;++i) a[i] = read(),SUM += a[i]; num = a[1]; bz[1] = 1; int tot = 1; for(int i = 2;i <= n;++i) if(a[i] * 2 <= a[1]) ++tot,bz[i] = 1,num += a[i]; if(num * 2 <= SUM) {puts("0");return 0;} printf("%d\n",tot); for(int i = 1;i <= n;++i) if(bz[i]) printf("%d ",i); return 0; }
B
题意
给出一个只含的字符串。相邻的两个可以看做是一个,问可以组成的子序列数量。
solve
正反各做一遍前(后)缀和。然后枚举,统计答案即可。
code
/* * @Author: wxyww * @Date: 2019-07-21 07:52:15 * @Last Modified time: 2019-07-21 08:08:24 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int N = 1000000 + 100; 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*10+c-'0'; c=getchar(); } return x*f; } char s[N]; ll sum1[N],sum2[N],ans; int main() { scanf("%s",s + 1); int n = strlen(s + 1); for(int i = 2;i <= n;++i) { sum1[i] = sum1[i - 1]; if(s[i] == 'v' && s[i - 1] == 'v') sum1[i]++; } for(int i = n - 1;i >= 1;--i) { sum2[i] = sum2[i + 1]; if(s[i] == 'v' && s[i + 1] == 'v') sum2[i]++; } for(int i = 1;i <= n;++i) if(s[i] == 'o') ans += sum2[i] * sum1[i]; cout<<ans; return 0; }
C
题意
有一个的房间。要在里面铺下图所示的瓷砖(长宽均为1),可以旋转。要求两块相邻的边两边的颜色不同。问方案数。答案对取模
solve
当房间相邻的两条边的瓷砖确定了之后。其他的所有瓷砖就也已经确定了。考虑到瓷砖间的相互影响,边缘铺的第一个瓷砖有种方案。其他的均有种方案。所以答案为
code
/* * @Author: wxyww * @Date: 2019-07-20 23:52:11 * @Last Modified time: 2019-07-21 07:52:45 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int N = 1010; const int mod = 998244353; 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*10+c-'0'; c=getchar(); } return x*f; } int f[N][N][4]; ll qm(ll x,ll y) { ll ret = 1; for(;y;y >>= 1,x = x * x % mod) if(y & 1)ret = ret * x % mod; return ret; } int main() { int n = read(),m = read(); cout<<qm(2,n + m); return 0; }
D
题意
构造一张有个点的无向图(无重边和自环)。满足:
- 边的总数为素数
- 所有点的度数均为素数
输出方案
solve
如果所有点的度数确定了。那么边数就是度数之和的一半。连边就很简单了。
所以考虑怎么确定点的度数。
猜想:必有至少一个满足为素数。
经测试,成立。
所以可以让所有点的度数都为或只要找到这个作为度数之和。然后边数就是。
设度数为的点有个,度数为的点有个。
列方程:
将所有点连成一个环之后,再连条边即可。
code
/* * @Author: wxyww * @Date: 2019-07-21 00:20:04 * @Last Modified time: 2019-07-21 07:53:25 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int N = 1000000 + 100; #define pi pair<int,int> int cnt; 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*10+c-'0'; c=getchar(); } return x*f; } int tot,dis[N],vis[N],a[N],K; void Eur() { for(int i = 2;i <= K;++i) { if(!vis[i]) dis[++tot] = i; for(int j = 1;j <= tot && 1ll * dis[j] * i <= K;++j) { vis[dis[j] * i] = 1; if(i % dis[j] == 0) break; } } } int A; pi ans[N]; priority_queue<pi>q; int p(int x) { if(x & 1) return x + 1; return x; } int main() { int n = read(); K = 100000; Eur(); for(A = n * 2;A <= n * 3;A ++) { if(A & 1) continue; if(!vis[A / 2]) break; } int Y = A - n * 2; int X = n - Y; for(int i = 1;i <= X;++i) q.push(make_pair(2,i)); for(int i = X + 1;i <= n;++i) q.push(make_pair(3,i)); for(int i = 1;i < n;++i) ans[++cnt] = make_pair(i,i + 1); ans[++cnt] = make_pair(n,1); Y /= 2; for(int i = 1;i <= n;i ++) { if(Y && !a[i] && !a[i + 2]) ans[++cnt] = make_pair(i,i + 2),Y--,a[i] = a[i + 2] = 1; } printf("%d\n",cnt); for(int i = 1;i <= cnt;++i) { printf("%d %d\n",ans[i].first,ans[i].second); } return 0; }
E
题意
有一个长度为字符串,只含有三种字符。选出一个长度大于等于的子回文串(不需要连续)
solve
从左右开始每次两边各找2个字符。这4个字符中,一定至少有一个出现次数大于1.将这个字符放入回文子串中。
code
/* * @Author: wxyww * @Date: 2019-07-21 01:31:22 * @Last Modified time: 2019-07-21 07:51:47 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; 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*10+c-'0'; c=getchar(); } return x*f; } const int N = 1000000 + 10; int n; char s[N]; char ans[N]; int a[4],cnt; int main() { scanf("%s",s + 1); n = strlen(s + 1); int l = 1,r = n - 1,bz = 0; while(l + 1 < r) { a[0] = a[1] = a[2] = 0; a[s[l] - 'a']++; a[s[l + 1] - 'a']++; a[s[r] - 'a']++; a[s[r + 1] - 'a']++; for(int i = 0;i <= 2;++i) { if(a[i] > 1) { ans[++cnt] = i + 'a'; break; } } l += 2;r -= 2; } for(int i = 1;i <= cnt;++i) putchar(ans[i]); if(l <= r) putchar(s[r]); for(int i = cnt;i >= 1;--i) putchar(ans[i]); return 0; }
F1
题意
有个长度为公分的布,要在上面每公分都染上颜色,整块布染恰好种颜色。颜色标号从到。染色需遵循:
1.从颜色到颜色依次,即必须先染标号小的颜***r>2.每次可以染任意一个区间,但必须满足这个区间之前的颜色是相同的。
询问将这块布染成所给颜色的方案数。
solve
区间。
表示染好这个区间的方案数。表示最小的颜色最后单独染的方案数。
所以就有,(为区间中的最小值)
然后枚举一个表示全染成最小颜色值的方案数。
那么就有
最后即为答案。
code
/* * @Author: wxyww * @Date: 2019-07-21 09:01:13 * @Last Modified time: 2019-07-21 10:48:02 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int N = 510,mod = 998244353; 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*10+c-'0'; c=getchar(); } return x*f; } int a[N],f[N][N],g[N][N]; int main() { int n = read(),m = read(); for(int i = 1;i <= n;++i) a[i] = read(); a[0] = 1e9; for(int i = 1;i <= n + 1;++i) g[i][i] = f[i][i] = f[i][i - 1] = g[i][i - 1] = 1; for(int len = 2;len <= n;++len) { for(int l = 1;l + len - 1 <= n;++l) { int r = l + len - 1,t = 0; for(int k = l;k <= r;++k) if(a[k] < a[t]) t = k; f[l][r] = g[l][r] = 1ll * f[l][t - 1] * f[t + 1][r] % mod; for(int k = l;k < r;++k) { f[l][r] = (f[l][r] + 1ll * g[l][k] * f[k + 1][r] % mod) % mod; } } } cout<<f[1][n]; return 0; }