题目链接

A. Charm Is Not Always Enough

模拟一下就可以了。

#include <bits/stdc++.h>
using namespace std; int T; int main() {
scanf("%d", &T);
while(T --) {
int n, m;
long long ans = 0;
scanf("%d%d", &n, &m);
while(n --) {
int x;
scanf("%d", &x);
x = x % m;
if(x == 0) continue;
ans = ans + 1LL * (m - x);
}
cout << ans << endl;
}
return 0;
}

B. Max and Alexis Plan to Conquer the World

打表。

设比例为$h$,可以发现$x$天之后的数量等于$n$乘上一个关于$h$的某种前缀和。

$h$只有$100$种,可以把每一种的前缀和都计算好,每组数据二分一下即可。

#include <bits/stdc++.h>
using namespace std; double h[105][4500]; void init() {
for(int i = 1; i <= 100; i ++) {
h[i][0] = 1.0;
for(int t = 1; t < 4500; t ++) {
h[i][t] = h[i][t - 1] + h[i][t - 1] * i / 100;
}
//printf("%lf\n", h[i][4499]);
}
} int main() {
init();
int T ;
scanf("%d", &T);
int cas = 1;
while(T -- > 0) {
double n;
scanf("%lf", &n);
int r;
scanf("%d", &r);
double p;
scanf("%lf", &p); int L = 0, R = 4499;
int ans = 0;
while(L <= R) {
int mid = (L + R) / 2;
if(n * h[r][mid] >= p) {
ans = mid;
R = mid - 1;
} else {
L = mid + 1;
}
}
printf("Case %d: %d\n", cas, ans);
cas ++;
}
}

C. Being Common is Too Mainstream

质因数分解,暴力。

#include <bits/stdc++.h>
using namespace std; //****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小 //计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的
// a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
a%=c;
b%=c;
long long ret=0;
while(b)
{
if(b&1){ret+=a;ret%=c;}
a<<=1;
if(a>=c)a%=c;
b>>=1;
}
return ret;
} //计算 x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
if(n==1)return x%mod;
x%=mod;
long long tmp=x;
long long ret=1;
while(n)
{
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
}
return ret;
} //以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;//合数
last=ret;
}
if(ret!=1) return true;
return false;
} // Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false; bool Miller_Rabin(long long n)
{
if(n<2)return false;
if(n==2)return true;
if((n&1)==0) return false;//偶数
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
for(int i=0;i<S;i++)
{
long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
if(check(a,n,x,t))
return false;//合数
}
return true;
} //************************************************
//pollard_rho 算法进行质因数分解
//************************************************
long long factor[100];//质因数分解结果(刚返回时是无序的)
int tol;//质因数的个数。数组小标从0开始 long long gcd(long long a,long long b)
{
if(a==0)return 1;//???????
if(a<0) return gcd(-a,b);
while(b)
{
long long t=a%b;
a=b;
b=t;
}
return a;
} long long Pollard_rho(long long x,long long c)
{
long long i=1,k=2;
long long x0=rand()%x;
long long y=x0;
while(1)
{
i++;
x0=(mult_mod(x0,x0,x)+c)%x;
long long d=gcd(y-x0,x);
if(d!=1&&d!=x) return d;
if(y==x0) return x;
if(i==k){y=x0;k+=k;}
}
}
//对n进行素因子分解
void findfac(long long n)
{
if(Miller_Rabin(n))//素数
{
factor[tol++]=n;
return;
}
long long p=n;
while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
findfac(p);
findfac(n/p);
} const long long mod = 1000000001LL;
const int maxn = 1e5 + 10;
long long a[maxn];
vector<long long> fac[maxn]; bool prime(long long x) {
if(x == 1) return 0;
for(long long i = 2; i * i <= x; i ++) {
if(x % i == 0) return 0;
}
return 1;
} int main() {
srand(time(NULL));
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
long long ans = 1;
if(n == 1) {
ans = a[1] % mod;
} else if(n == 2) {
long long g = gcd(a[1], a[2]);
for(int i = 1; i <= n; i ++) {
a[i] /= g;
ans = ans * a[i] % mod;
}
} else if(n == 3) {
long long g;
g = gcd(a[1], gcd(a[2], a[3]));
for(int i = 1; i <= n; i ++) {
a[i] /= g;
}
g = gcd(a[1], a[2]);
a[1] /= g;
a[2] /= g;
g = gcd(a[2], a[3]);
a[2] /= g;
a[3] /= g;
g = gcd(a[1], a[3]);
a[1] /= g;
a[3] /= g;
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
} else if(n <= 1000) {
for(int i = 1; i <= n; i ++) {
if(a[i] == 1) continue;
tol = 0;
findfac(a[i]);
for(int j = 0; j < tol; j ++) {
fac[i].push_back(factor[j]);
}
}
for(int i = 1; i <= n; i ++) {
for(int j = 0; j < fac[i].size(); j ++) {
if(a[i] % fac[i][j]) continue;
int num = 0;
for(int k = 1; k <= n; k ++) {
if(a[k] % fac[i][j] == 0) num ++;
}
if(num < 2) continue;
for(int k = 1; k <= n; k ++) {
if(a[k] % fac[i][j] == 0) {
a[k] /= fac[i][j];
}
}
}
}
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
} else {
for(long long x = 2; x <= 601; x ++) {
if(!prime(x)) continue;
while(1) {
int num = 0;
for(int i = 1; i <= n; i ++) {
if(a[i] % x == 0) num ++;
}
if(num < 2) break;
for(int i = 1; i <= n; i ++) {
if(a[i] % x == 0) a[i] /= x;
}
}
}
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
}
printf("%lld\n", ans);
return 0;
} /*
10
1 2 3 4 5 6 7 8 9 10
*/

D. Shaat Chara

对于第$i$堆石头,要使得拿走第$i$堆的若干颗石头变成必胜态,也就是要使得剩下的所有石头异或和为$0$。

#include <bits/stdc++.h>
using namespace std; const long long mod = 1000000007LL;
const int maxn = 2e5 + 10;
int T, n;
int a[maxn]; int main() {
scanf("%d", &T);
int cas = 1;
while(T --) {
scanf("%d", &n);
int Xor = 0;
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
Xor = Xor ^ a[i];
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
Xor = Xor ^ a[i];
if(Xor < a[i]) ans ++;
Xor = Xor ^ a[i];
}
printf("Case %d: %d\n", cas ++, ans);
}
return 0;
}

E. Just One Swap

如果每个数字都不一样,答案就是$C_n^2$。

否则,相同的数字交换有$1$种情况,再计算不同数字交换的方案数。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int T;
int a[maxn]; int main() {
scanf("%d", &T);
while(T --) {
memset(a, 0, sizeof a);
int n;
scanf("%d", &n);
int y = n;
while(n --) {
int x;
scanf("%d", &x);
a[x] ++;
}
int ok = 1;
for(int i = 1; i <= 100000; i ++) {
if(a[i] > 1) ok = 0;
} long long ans = 0;
if(ok) {
ans = 1LL * y * (y - 1) / 2;
} else {
ans = 1LL;
long long sum = 0;
for(int i = 1; i <= 100000; i ++) {
ans = ans + sum * a[i];
sum = sum + a[i];
}
}
printf("%lld\n", ans);
}
return 0;
}

F. Halum and Candies

贪心,二分。

这题最直观的做法是每次将最大的$k$个数字减$1$,直到不能操作为止,但是在题目的数据规模下容易超时。

较为容易的写法是二分答案+验证,假设二分到$x$个人,只要看$\sum\limits_{i = 1}^n {\min (a[i],x)}$和$x*k$的大小关系即可。

#include <bits/stdc++.h>
using namespace std; int T, n, k;
const int maxn = 1e5 + 10;
long long a[maxn]; int check(long long x) {
long long p = 0;
for(int i = 1; i <= n; i ++) {
p = p + min(x, a[i]);
}
if(p >= x * k) return 1;
return 0;
} int main() {
int cas = 1;
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
long long L = 0;
long long R = 1e12;
long long ans = 0;
while(L <= R) {
long long mid = (L + R) / 2;
if(check(mid)) ans = mid, L = mid + 1;
else R = mid - 1;
}
printf("Case %d: %lld\n", cas ++, ans);
}
return 0;
} /*
3
3 3
1 2 3
3 1
1 2 3
3 2
3 2 4
*/

G. XOR 'em all!

线段树。

每个节点存储每一种$1$的个数的最小的位置,以及转换后的即可。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + 10;
int T, n, q;
int a[maxn], cnt[2 * maxn];
int s[maxn * 4][2][25];
int p[maxn * 4], f[maxn * 4];
int ans, B, v; int lowbit(int x) {
return x & (-x);
} void init() {
for(int i = 1; i < (1 << 20); i ++) {
cnt[i] = cnt[i - lowbit(i)] + 1;
}
} void pushUp(int rt) {
for(int i = 0; i < 21; i ++) {
s[rt][0][i] = min(s[2 * rt][p[2 * rt]][i],
s[2 * rt + 1][p[2 * rt + 1]][i]);
s[rt][1][i] = min(s[2 * rt][p[2 * rt] ^ 1][i],
s[2 * rt + 1][p[2 * rt + 1] ^ 1][i]);
}
p[rt] = 0;
} void pushDown(int rt) {
if(f[rt] == 0) return;
p[2 * rt] = (p[2 * rt] + f[rt]) % 2;
f[2 * rt] = (f[2 * rt] + f[rt]) % 2;
p[2 * rt + 1] = (p[2 * rt + 1] + f[rt]) % 2;
f[2 * rt + 1] = (f[2 * rt + 1] + f[rt]) % 2;
f[rt] = 0;
} void build(int l, int r, int rt) {
p[rt] = 0;
f[rt] = 0;
if(l == r) {
for(int t = 0; t < 2; t ++) {
for(int i = 0; i < 21; i ++) {
s[rt][t][i] = n + 1;
}
}
s[rt][0][a[l]] = l;
s[rt][1][20 - a[l]] = l;
return;
}
int mid = (l + r) / 2;
build(l, mid, 2 * rt);
build(mid + 1, r, 2 * rt + 1);
pushUp(rt);
} void update(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
p[rt] = (p[rt] + 1) % 2;
f[rt] = (f[rt] + 1) % 2;
return;
}
pushDown(rt);
int mid = (l + r) / 2;
if(L <= mid) update(L, R, l, mid, 2 * rt);
if(R > mid) update(L, R, mid + 1, r, 2 * rt + 1);
pushUp(rt);
} void query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
for(int i = 0; i < 21; i ++) {
if(s[rt][p[rt]][i] > n) continue;
if(abs(i - v) < B) {
B = abs(i - v);
ans = s[rt][p[rt]][i];
} else if(abs(i - v) == B) {
ans = min(ans, s[rt][p[rt]][i]);
}
}
return;
}
pushDown(rt);
int mid = (l + r) / 2;
if(L <= mid) query(L, R, l, mid, 2 * rt);
if(R > mid) query(L, R, mid + 1, r, 2 * rt + 1);
pushUp(rt);
} int main() {
init();
scanf("%d", &T);
int cas = 1;
while(T --) {
printf("Case %d:\n", cas ++);
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
a[i] = cnt[a[i]];
}
build(1, n, 1);
while(q --) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1) {
scanf("%d", &v);
v = cnt[v];
B = 100;
ans = n + 1;
query(l, r, 1, n, 1);
printf("%d\n", ans);
} else {
update(l, r, 1, n, 1);
}
}
}
return 0;
} /*
1
10 9
47810 337106 289217 728190 763968 210307 934334 929186 401808 365768
2 8 10
1 2 10 611293
2 2 4
1 1 8 422298
2 6 8
2 2 10
1 5 6 180197
2 7 8
1 4 8 712158
*/

H. Simple Path

树形$dp$。

注意点:这题数据有问题,题面上说每条边都是从$u$到$v$的,但事实上不是。

#include <bits/stdc++.h>
using namespace std; const long long mod = 1000000007LL;
const int maxn = 4e5 + 10;
int T;
int h[maxn];
int v[maxn];
long long w[maxn];
int nx[maxn];
int n;
int sz[maxn];
long long ans;
int cnt;
int f[maxn]; void add(int a, int b, long long c) {
v[cnt] = b;
w[cnt] = c;
nx[cnt] = h[a];
h[a] = cnt ++;
} void SZ(int x) {
sz[x] = 1;
f[x] = 1;
for(int i = h[x]; i != -1; i = nx[i]) {
if(!f[v[i]]) {
SZ(v[i]);
sz[x] += sz[v[i]];
}
}
} void DP(int x, long long sum, int dep) {
f[x] = 1;
for(int i = h[x]; i != -1; i = nx[i]) {
if(f[v[i]]) continue;
// printf(" %d -> %d \n", x, v[i]);
long long A = 1LL * sz[v[i]] * sum % mod;
long long B = 1LL * sz[v[i]] * sz[v[i]] % mod;
B = 1LL * B * dep % mod;
long long C = (A - B + mod) % mod;
C = 1LL * C * w[i] % mod;
// cout << x << " debug " << C << endl;
ans = (ans + C) % mod;
long long G = 1LL * sz[v[i]];
G = (sum + G) % mod;
DP(v[i], G, dep + 1);
} //printf("debug %d %lld\n", x, dp[x]);
} int main() {
scanf("%d", &T);
int cas = 1;
while(T --) {
scanf("%d", &n);
cnt = 0;
for(int i = 1; i <= n; i ++) {
h[i] = -1;
sz[i] = 0;
f[i] = 0;
}
for(int i = 1; i < n; i ++) {
int a, b;
long long c;
scanf("%d%d%lld", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
SZ(1);
for(int i = 1; i <= n; i ++) {
if(sz[i] <= 0) while(1) {}
}
for(int i = 1; i <= n; i ++) {
f[i] = 0;
}
ans = 0;
DP(1, sz[1], 1);
printf("Case %d: %lld\n", cas ++, ans);
}
return 0;
} /*
2
7
1 2 3
1 3 2
2 4 1
2 5 4
3 6 6
3 7 8 6
1 2 3
1 3 2
1 4 4
3 5 7
3 6 1
*/

2017 Bangladesh National High School Programming Contest ( National Round, Senior Group ), NHSPC 2017 题解的更多相关文章

  1. Codeforces Gym101606 A.Alien Sunset (2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017))

    2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017) 寒假第一次组队训练赛,和学长一起训练,题目难度是3颗星,我和猪队友写 ...

  2. 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)

    A. Alien Sunset 暴力枚举答案即可. #include<cstdio> int n,i,mx; struct P{ int h,r,t; bool night(int x){ ...

  3. 2017, X Samara Regional Intercollegiate Programming Contest 题解

    [题目链接] A - Streets of Working Lanterns - 2 首先将每一个括号匹配串进行一次缩减,即串内能匹配掉的就匹配掉,每个串会变成连续的$y$个右括号+连续$z$个左括号 ...

  4. 2019.04.11 第四次训练 【 2017 United Kingdom and Ireland Programming Contest】

    题目链接:  https://codeforces.com/gym/101606 A: ✅ B: C: ✅ D: ✅ https://blog.csdn.net/Cassie_zkq/article/ ...

  5. 2017 Wuhan University Programming Contest (Online Round) Lost in WHU 矩阵快速幂 一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开。

    /** 题目:Lost in WHU 链接:https://oj.ejq.me/problem/26 题意:一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开. ...

  6. 2017 Wuhan University Programming Contest (Online Round) C. Divide by Six 分析+模拟

    /** 题目:C. Divide by Six 链接:https://oj.ejq.me/problem/24 题意:给定一个数,这个数位数达到1e5,可能存在前导0.问为了使这个数是6的倍数,且没有 ...

  7. 2017 Wuhan University Programming Contest (Online Round) B Color 树形dp求染色方法数

    /** 题目:Color 链接:https://oj.ejq.me/problem/23 题意:给定一颗树,将树上的点最多染成m种颜色,有些节点不可以染成某些颜色.相邻节点颜色不同.求染色方法数. 思 ...

  8. [寒假集训第一场]gym101606 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)

    3星场 难度在于英文题面太难读懂了QAQ 看样例猜题意的我 博客园的c++主题真丑 A Alien Sunset \(description\) 有\(n\)个星球,每个星球自转时间不一样,所以一天的 ...

  9. Codeforces Gym101606 C.Cued In (2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017))

    C Cued In 这个题是打球的.都忘了写的什么了... 代码: 1 #include<iostream> 2 #include<cstring> 3 #include< ...

随机推荐

  1. TV 开发相关

    1.设置全屏,隐藏虚拟按键 1.activity oncreate中 @Override 2 protected void onCreate (Bundle savedInstanceState) { ...

  2. Spring IOC 容器

    <bean name="userBean" class="com.nuts.demo.spring.UserBean"> <property ...

  3. centos7 源码构建、安装dubbo-monitor

    按照官方文档 ,发现dubbo-monitor-simple-x.x.x-assembly.tar.gz  下载不下来(地址访问不了),那么就自己下载源码构建吧. 我的zookeeper,hadoop ...

  4. jquery中美元符号命名冲突问题解决

    在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$('#msg')等同于JQuery('#msg') 的写法.然而,当我们引入多个js库后,在另外一个js库 ...

  5. 2017萧山第5场(2016 Pacific Northwest - Division 1)

    B:Buggy Robot [题意] 一个n*m的地图(1≤n, m≤50),有一个入口和一个出口.给定一个命令序列(上,下,左,右),如果碰到障碍或者边际就忽略.问至少加入或删除多少个的命令,使得能 ...

  6. 20155336 2016-2017-2《JAVA程序设计》第七周学习总结

    20155336 2016-2017-2<JAVA程序设计>第七周学习总结 教材学习内容总结 第十三章 认识时间与日期 格林威治标准时间:简称GMT时间,参考格林威治皇家天文台的标准太阳时 ...

  7. 20155306 2016-2017-2 《Java程序设计》第6周学习总结

    20155306 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 输入/输出 10.1 InputStream与OutputStream 如果要将数据 ...

  8. pta 一

    7-1 打印沙漏 (20 分) 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个“*”,要求按下列格式打印 ***** *** * *** ***** 所谓“沙漏形状”,是指每行输出奇数 ...

  9. 【数据库】SQL经典面试题 - 行列转换二 - 列转行

    本帖子是行转列的一个逆向操作——列转行,看下面一个面试题 面试题2: 柠檬班第30期学生要毕业了,他们的Linux.MySQL.Java成绩数据表 tb_lemon_grade_column中, 表中 ...

  10. align-items和align-content的区别

    最近在研究flex布局,容器中有两个属性,是用来定义crossAxis测轴排列方式的.一开始接触align-items还可以理解感觉不难,后来看到align-content就感觉有点混淆了,特开一篇博 ...