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 ...
随机推荐
- 洛谷 P2376 [USACO09OCT]津贴Allowance 解题报告
P2376 [USACO09OCT]津贴Allowance 题目描述 作为创造产奶纪录的回报,\(Farmer\) \(John\)决定开始每个星期给\(Bessie\)一点零花钱. \(FJ\)有一 ...
- 洛谷P2605 基站选址
神TM毒瘤线段树优化DP......新姿势get. 题意:有n个村庄,在里面选不多于k个建立基站. 建立基站要ci的费用.如果一个村庄方圆si内没有基站,那么又要支出wi的费用.求最小费用. 解:很显 ...
- 使用highlight.js高亮静态页面的语言代码
显示静态的代码其实html的pre标签基本可以满足需求了,至少不会将换行的文本显示成一堆字符串. 不过能使静态的文本能高亮显示,倒更炫酷一点.其实很简单的,引入highlight.js包,可以使用cd ...
- 基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二)
http://blog.csdn.net/jiuqiyuliang/article/details/19967031 目录: 基于asp.net + easyui框架,一步步学习easyui-data ...
- LeetCode 8 有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空字符串可被认 ...
- First non-repeating character in a stream
First non-repeating character in a stream Given an input stream of n characters consisting only of s ...
- 个推Node.js 微服务实践:基于容器的一站式命令行工具链
作者:个推Node.js 开发工程师 之诺 背景与摘要 由于工程数量的快速增长,个推在实践基于 Node.js 的微服务开发的过程中,遇到了如下问题: 1. 每次新建项目都需要安装一次依赖,这些依赖之 ...
- python的内置模块re模块方法详解以及使用
正则表达式 一.普通字符 . 通配符一个.只匹配一个字符 匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符 >>> import re ...
- Linux ------清除内存中的cache
首先以Centos6.4的来说,Centos7有些区别 一.buffer/cache/swap的介绍 #cat /etc/redhat-release #查看系统版本 CentOS release ...
- 在ajax请求后台时在请求标头RequestHeader加token
情景:为了保证系统数据的安全性,一般前后台之间的数据访问会有授权与验证,这里的Token机制相对于Cookie支持跨域访问,在RESTful API里面,验证一般可以使用POST请求来通过验证,使服务 ...