2017 JUST Programming Contest 2.0 题解
【题目链接】
首先,$n>m$或$k>m$或$k>n$就无解。
设$p = \frac{A}{B}$,$ans = C_{n - 1}^{k - 1}{\left( {\frac{A}{B}} \right)^{k}}{\left( {\frac{B-A}{B}} \right)^{n - k}} = \frac{{\left( {n - 1} \right)! \times {A^k} \times {{\left( {B - A} \right)}^{n - k}}}}{{\left( {k - 1} \right)! \times \left( {n - k} \right)! \times {B^n}}}$。令分子为$p$,分母为$q$,最终的答案为$p$*($q$的逆元)。
#include <bits/stdc++.h>
using namespace std; const long long mod = 1e9 + 7;
const int maxn = 2e5 + 10;
long long f[maxn]; long long m, n, k;
char s[maxn]; long long qpow(long long a, long long b) {
long long res = 1LL;
a = a % mod;
while(b) {
if(b & 1) res = (res * a) % mod;
b = b / 2;
a = (a * a) % mod;
}
return res;
} long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
} void init() {
f[0] = 1LL;
for(long long i = 1; i <= 100000; i ++) {
f[i] = (f[i - 1] * i) % mod;
}
} int main() {
init();
cin >> m >> n >> k >> s;
if(n > m || k > m || k > n) {
printf("0\n");
return 0;
}
if(s[0] == '1' && n == k) {
printf("1\n");
return 0;
}
if(s[0] == '1') {
printf("0\n");
return 0;
}
if(s[0] == '0' && s[2] == '0' && s[3] == '0' && s[4] == '0') {
printf("0\n");
return 0;
} long long A = 0;
long long B = 1000LL;
for(int i = 2; i <= 4; i ++) {
A = A * 10LL + s[i] - '0';
} long long p, q; p = f[n - 1] * qpow(A, k) % mod;
p = p * qpow(B - A, n - k) % mod; q = f[k - 1] * f[n - k] % mod;
q = q * qpow(B, n) % mod; long long x = p * mod_reverse(q, mod) % mod;
printf("%lld\n", x);
return 0;
}
B - So You Think You Can Count?
设$dp[i]$表示以$i$为结尾的方案数,每个位置最多往前扫$10$位。
#include <bits/stdc++.h>
using namespace std; const long long mod = 1e9 + 7;
const int maxn = 1e5 + 10;
char s[maxn];
int n;
long long dp[maxn]; long long DP(int x) {
if(x < 0) return 1LL;
return dp[x];
} int main() {
scanf("%d", &n);
scanf("%s", s);
int len = strlen(s);
dp[0] = 1LL;
for(int i = 1; i < len; i ++) {
int tmp[20];
for(int j = 0; j <= 9; j ++) {
tmp[j] = 0;
}
for(int pre = i; pre >= 0; pre --) {
if(tmp[s[pre] - '0']) break;
tmp[s[pre] - '0'] = 1;
dp[i] = (dp[i] + DP(pre - 1)) % mod;
}
}
printf("%lld\n", dp[len - 1]);
return 0;
}
最短路,数据有点水,没把spfa卡住。
#include <bits/stdc++.h>
using namespace std; const int maxn = 2e5 + 10; int S, T, n, m;
char name[maxn][25];
int h[maxn], nx[maxn], to[maxn], c[maxn], sz;
int t1[30], t2[30]; int cost(int x, int y) {
memset(t1, 0, sizeof t1);
memset(t2, 0, sizeof t2); for(int i = 0; name[x][i]; i ++){
if(name[x][i] >= 'a' && name[x][i] <= 'z') {
t1[name[x][i] - 'a'] ++;
}
if(name[x][i] >= 'A' && name[x][i] <= 'Z') {
t1[name[x][i] - 'A'] ++;
}
} for(int i = 0; name[y][i]; i ++){
if(name[y][i] >= 'a' && name[y][i] <= 'z') {
t2[name[y][i] - 'a'] ++;
}
if(name[y][i] >= 'A' && name[y][i] <= 'Z') {
t2[name[y][i] - 'A'] ++;
}
} int num = 0;
for(int i = 0; i < 26; i ++) {
if(t1[i] && t2[i]) num ++;
}
return num;
} void add(int x, int y, int z) {
to[sz] = y;
c[sz] = z;
nx[sz] = h[x];
h[x] = sz++;
} int dis[maxn], f[maxn]; void spfa() {
for(int i = 1 ;i <= n; i ++) {
f[i] = 0;
dis[i] = 0x7FFFFFFF;
}
queue<int> Q;
Q.push(S);
f[S] = 1;
dis[S] = 0;
while(!Q.empty()) {
int top = Q.front();
Q.pop();
f[top] = 0;
for(int i = h[top]; i != -1; i = nx[i]) {
if(dis[top] + c[i] < dis[to[i]]) {
dis[to[i]] = dis[top] + c[i];
if(f[to[i]] == 0) {
f[to[i]] = 1;
Q.push(to[i]);
}
}
}
}
} int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) {
scanf("%s", name[i]);
h[i] = -1;
}
for(int i = 1; i <= m; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v, cost(u, v));
add(v, u, cost(u, v));
}
scanf("%d%d", &S, &T);
spfa();
printf("%d\n", dis[T]);
return 0;
}
模拟。
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + 10;
char s[maxn]; int main() {
int T;
scanf("%d", &T);
while(T --) {
scanf("%s", s); int num1=0, num2=0, num3=0;
for(int i = 0; s[i];i ++) {
if(s[i]>='a'&&s[i]<='z') num1++;
else if(s[i]>='A'&&s[i]<='Z') num1++;
else if(s[i]>='0'&&s[i]<='9') num2++;
else if(s[i] =='!' || s[i] =='?'||s[i] == '@') {
num3++;
}
}
if(num1 < 4) {
printf("The last character must be a letter.\n");
continue;
}
if(num2 < 4) {
printf("The last character must be a digit.\n");
continue;
}
if(num3 < 2) {
printf("The last character must be a symbol.\n");
continue;
}
printf("The last character can be any type.\n");
}
return 0;
}
由于验证的复杂度只有$O(26)$,因此可以枚举答案。
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int n, m;
char s[maxn];
long long f[maxn]; int main() {
scanf("%s", s);
for(int i = 0; s[i]; i ++) {
f[s[i] - 'a'] ++;
}
long long ans = -1;
long long mn = -1;
for(long long i = 2; i <= 300000; i ++) {
long long tmp = 0;
for(int j = 0; j < 26; j ++) {
tmp = tmp + (f[j] % i) * f[j];
}
if(mn == -1 || tmp < mn) {
mn = tmp;
ans = i;
}
}
printf("%lld\n", ans);
return 0;
}
二分查找。
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int n, m;
int a[maxn]; int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
scanf("%d", &m);
while(m --) {
int x;
scanf("%d", &x);
int L = 1, R = n, pos = -1;
while(L <= R) {
int mid = (L + R) / 2;
if(a[mid] >= x) pos = mid, R = mid - 1;
else L = mid + 1;
}
if(pos == -1) printf("Dr. Samer cannot take any offer :(.\n");
else printf("%d\n", a[pos]);
}
return 0;
}
模拟。
#include <bits/stdc++.h>
using namespace std; int main() {
int n, m;
cin>> n>>m;
if(m % n == 0) printf("YES\n");
else printf("NO\n");
return 0;
}
这题为单调栈经典问题,但是由于数值范围只有$50$,因此可以枚举数值。
#include <bits/stdc++.h>
using namespace std; const int maxn = 2e5 + 10;
int n, m;
int a[maxn];
int b[maxn];
int num[maxn]; int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
}
for(int i = 0; i<= 100; i ++) num[i] = 200000;
for(int j = n; j>=1; j--) {
b[j] = 200000;
for(int k = 50; k >= a[j] + 1; k--){
if(num[k] < b[j]) b[j] = num[k];
}
num[a[j]] = j;
if(b[j] != 200000) b[j] = a[b[j]];
else b[j] = -1;
}
for(int i =1 ;i <= n; i ++) {
printf("%d ", b[i]);
}
return 0;
}
I - Husam and the Broken Present 1
对主对角线开根号来求解。
#include <bits/stdc++.h>
using namespace std; int main() {
int n;
cin>> n;
int x;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j++){
cin>>x;
if(i == j){
int num = sqrt(1.0 * x);
while(num * num > x) num--;
while(num*num<x)num++;
printf("%d ", num);
} }
}
return 0;
}
J - Husam and the Broken Present 2
先删除被包含的那些数组,剩下的可以进行状压$dp$来决策放置顺序。$dp[st][v]$表示有$st$状态里面的子数组已经放置好了,最后放的是$v$的最小花费,和TSP是一样的问题。
#include <bits/stdc++.h>
using namespace std; const int maxn = 1000;
vector<int> vec[maxn], t[maxn];
int cost[20][20]; int n;
int dp[70000][17]; int han(vector<int>& a, vector<int>& b) {
// a 是否在 b 中
if(b.size() < a.size()) return 0;
for(int i = 0; i < b.size(); i ++) {
int L = i, R = i + a.size() - 1;
if(R >= b.size()) break;
int fail = 0;
for(int j = 0; j < a.size(); j ++) {
if(a[j] != b[L + j]) fail = 1;
}
if(fail == 0) return 1;
}
return 0;
} int cal(int x, int y) {
// x 后面 接 y
int res = 0;
for(int i = 0; i < t[x].size(); i ++) {
if(t[x].size() - i > t[y].size()) continue;
int fail = 0;
for(int j = i; j < t[x].size(); j ++) {
if(t[x][j] != t[y][j - i]) fail = 1;
}
//printf("!!! %d, %d\n", i, fail);
if(fail == 0) {
res = t[x].size() - i;
break;
} }
return t[y].size() - res;
} bool cmp(const vector<int> &a, const vector<int> &b) {
return a.size() > b.size();
} int main() {
scanf("%d", &n);
for(int i = 0; i < n; i ++) {
int x;
scanf("%d", &x);
while(x--){
int p;
scanf("%d", &p);
vec[i].push_back(p);
}
}
sort(vec, vec + n, cmp);
int sz = 0;
t[sz++] = vec[0];
for(int i = 1; i < n; i ++) {
int fail = 0;
for(int j = 0; j < sz; j ++) {
if(han(vec[i], t[j])) {
fail = 1;
break;
}
}
if(fail) continue;
t[sz ++] = vec[i];
} n = sz; /*
for(int i = 0; i < n; i ++) {
for(int j = 0; j < t[i].size(); j ++) {
cout << t[i][j] << " ";
}
cout << endl;
}
*/ for(int i = 0; i < n; i ++) {
for(int j = 0; j < n; j ++) {
if(i == j) continue;
cost[i][j] = cal(i, j);
}
} for(int st = 0; st < (1 << n); st ++) {
for(int i = 0; i < n; i ++) {
dp[st][i] = 200000;
}
}
for(int i = 0; i < n; i ++) {
dp[1 << i][i] = t[i].size();
} for(int st = 1; st < (1 << n); st ++) {
for(int pre = 0; pre < n; pre ++) {
if(((1 << pre) & st) == 0) continue;
for(int now = 0; now < n; now ++) {
if((1 << now) & st) continue;
dp[st | (1 << now)][now] = min(dp[st | (1 << now)][now], dp[st][pre] + cost[pre][now]);
}
}
} int ans = dp[(1 << n) - 1][0];
for(int i = 0; i < n; i ++) {
ans = min(ans, dp[(1 << n) - 1][i]);
}
printf("%d\n", ans); return 0;
} /*
3
2 1 2
4 3 4 5 6
3 2 3 4 */
2017 JUST Programming Contest 2.0 题解的更多相关文章
- gym101343 2017 JUST Programming Contest 2.0
A.On The Way to Lucky Plaza (数论)题意:m个店 每个店可以买一个小球的概率为p 求恰好在第m个店买到k个小球的概率 题解:求在前m-1个店买k-1个球再*p ...
- 2018 JUST Programming Contest 1.0 题解
题目链接 gym101778 Problem A 转化成绝对值之后算一下概率.这个题有点像 2018 ZOJ Monthly March Problem D ? 不过那个题要难一些~ #includ ...
- gym101532 2017 JUST Programming Contest 4.0
台州学院ICPC赛前训练5 人生第一次ak,而且ak得还蛮快的,感谢队友带我飞 A 直接用claris的模板啊,他模板确实比较强大,其实就是因为更新的很快 #include<bits/stdc+ ...
- 2017 JUST Programming Contest 3.0 B. Linear Algebra Test
B. Linear Algebra Test time limit per test 3.0 s memory limit per test 256 MB input standard input o ...
- 2017 JUST Programming Contest 3.0 I. Move Between Numbers
I. Move Between Numbers time limit per test 2.0 s memory limit per test 256 MB input standard input ...
- 2017 JUST Programming Contest 3.0 D. Dice Game
D. Dice Game time limit per test 1.0 s memory limit per test 256 MB input standard input output stan ...
- 2017 JUST Programming Contest 3.0 H. Eyad and Math
H. Eyad and Math time limit per test 2.0 s memory limit per test 256 MB input standard input output ...
- 2017 JUST Programming Contest 3.0 K. Malek and Summer Semester
K. Malek and Summer Semester time limit per test 1.0 s memory limit per test 256 MB input standard i ...
- 2017 JUST Programming Contest 3.0 E. The Architect Omar
E. The Architect Omar time limit per test 1.0 s memory limit per test 256 MB input standard input ou ...
随机推荐
- 前端学习 -- Css -- 有序列表和无序列表
列表就相当于去超市购物时的那个购物清单, 在HTML也可以创建列表,在网页中一共有三种列表: 1.无序列表 2.有序列表 3.定义列表 无序列表 - 使用ul标签来创建一个无序列表 - 使用li在ul ...
- emoji表情存储到数据库的方法
方案1:修改数据库编码 为什么我们设置表的的字符类型为utf8却不能存放emoji呢?原来utf8可能是2或3或4个字节,而mysql的utf8是3个字节,存放一个emoji是需要4个字节的,自然不够 ...
- EOJ #276
题面 感觉是个套路题,不是特别难(然而卡常 直接做不可做,改成算每个数的贡献 暴力的想法是容斥,即记录每个数在每行里的出现情况,从总方案中扣掉每一行都没选到这个数的方案,复杂度$O(n^3)$ 我们发 ...
- 解题:UOJ #46 玄学
题面 二进制分组,修改把区间拆开丢在后面,合并的时候归并最后两块:查询在对应节点上二分答案 #include<cstdio> #include<cstring> #includ ...
- java基础基础总结----- Math(随机数)
前言:math类中感觉最好玩的应该就是随机数 代码: package com.day13.math; import java.util.Random; /** * 类说明 :Math * @autho ...
- python爬虫 Scrapy2-- 爬取豆瓣电影TOP250
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- [应用篇]第二篇 JSP自带标签介绍
JSP 有以下三类标签: 指令:JSP Directive 指令标签用于设置与整个 JSP 页面相关的属性,非常常用. 下面的三种标签是我们使用频率最高的 标签 jsp标签 描述 <%@ pag ...
- [转载]Remote Desktop Manager 9.0.10.0 Enterprise 附企业版注册码 (强大的远程控制软件)
http://www.52xiazai.net/pcsoft/network/yuanchen/20131206/2429.html
- [转载]使用 NuGet 管理项目库
原文:http://msdn.microsoft.com/zh-cn/magazine/hh547106.aspx 无论多么努力,Microsoft 也没办法提供开发人员所需要的每一个库. 虽然 Mi ...
- asp.net分页之AJAX 分页
查询功能是开发中最重要的一个功能,大量数据的显示,我们用的最多的就是分页. 在ASP.NET 中有很多数据展现的控件,比如Repeater.GridView,用的最多的GridView,它同时也自带了 ...