Codeforces round341 div2
A:给出n个数,要求从中选数使得和最大且和为偶数;
统计所有数之和,若奇数个数 Mod 2 == 1,答案减去最小的那个奇数。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int n,num = 0;
long long a,Ans = 0,minx = 1e18;
int main() {
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%I64d",&a);Ans += a;
if(a % 2 == 1) num ++,minx = min(minx,a);
}
Ans -= (num % 2 == 0) ? 0 : minx;
cout<<Ans;
}
B:给出1000*1000 矩阵上的一些点,问有多少对点在同一条对角线上。
我们把所有的点化成直线解析式的形式,用桶装一下,最后统计答案就可以了。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int n,a,b;
long long Ans = 0,N[3010][2],M[3010][2];
int main() {
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&a,&b);
int x = b - a;
if(x < 0) N[-1 * x][0] ++;
else N[x][1] ++;
int y = b + a;
if(y < 0) M[-1 * y][0] ++;
else M[y][1] ++;
}
for(int i = 0;i <= 2005;i ++)
{
for(int j = 0;j <= 1;j ++)
{
Ans += (N[i][j] * (N[i][j] - 1)) / 2;
Ans += (M[i][j] * (M[i][j] - 1)) / 2;
}
}
cout<<Ans;
return 0;
}
C:给出n个数对(l[i],r[i]),以及一个质数p,现在n个数,每个数i的值是一个l[i]到r[i]之间的随机数,(这n个数构成了一个环),每当有val[i]* val[i+1] 或者val[i] *val[i-1]被p整除,那么就会有2000的代价,求最后的代价期望。
因为p是质数,这道题简单了许多。
我们对于每个i统计它的取值范围内有多少个p的倍数,设为num[i],那么4000*num[i]*All除以K[i]就是他对答案的贡献(All是所有数取值的总方案数,K[i]是i取值的方案数(即r[i]-l[i]+1),乘4000是因为对左右都有贡献。),但是要除去左右两边都是p的倍数的情况,所以再减去2000*num[i]*num[i+1]*All除以K[i]再除以K[i+1],只考虑往后相同的情况,不然会多减(其实就是一个简单的容斥),然后最后把答案除以All就是期望辣,但是All是一个很大的数,我们发现之前乘了All,之后又除了,所以说直接约掉就行了。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
#define d(x) double(x)
using namespace std;
long long n,p,A[200010],B[200010],num[200010];
double Ans = 0,tim = 1;
int main() {
cin>>n>>p;
for(int i = 1;i <= n;i ++)
scanf("%I64d%I64d",&A[i],&B[i]);
A[n + 1] = A[1];
B[n + 1] = B[1];
A[0] = A[n];
B[0] = B[n];
for(int i = 0;i <= n + 1;i ++)
num[i] = B[i] / p - (A[i] - 1) / p;
for(int i = 1;i <= n;i ++)
{
Ans += d(4000) * d(num[i]) / d(B[i] - A[i] + 1);
Ans -= d(2000) * d(num[i]) * d(num[i + 1]) / d(B[i] - A[i] + 1) / d(B[i + 1] - A[i + 1] + 1);
}
printf("%0.10f",Ans);
return 0;
}
D:给出12个对于x,y,z的函数f[i](x,y,z),询问其中的最大值,输出那个函数。
(其中函数的运算都是幂运算,比如x^y^z,结果可能很大,x,y,z<=200)。
首先直接使用pow函数是会爆精度的,我们考虑用其他方式来减小答案却又不影响比较,于是想到了log(这个经常用到,要记住),x^y^z就变成了log(x)*pow(y,z)这样以后精度就没有太大问题了,但是还是要开long double,不然狂wa(python大法好)。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
long double Ans = -1 * 1e300,x,y,z,A[14];
int p;
int main() {
cin>>x>>y>>z;
A[1] = pow(y,z) * log(x);
A[2] = pow(z,y) * log(x);
A[3] = A[4] = z * y * log(x);
A[5] = pow(x,z) * log(y);
A[6] = pow(z,x) * log(y);
A[7] = A[8] = x * z * log(y);
A[9] = pow(x,y) * log(z);
A[10] = pow(y,x) * log(z);
A[11] = A[12] = x * y * log(z);
for(int i = 1;i <= 12;i ++)
{
if(A[i] > Ans)
{
Ans = A[i];
p = i;
}
}
if(p == 1) cout<<"x^y^z";
if(p == 2) cout<<"x^z^y";
if(p == 3) cout<<"(x^y)^z";
if(p == 4) cout<<"(x^z)^y";
if(p == 5) cout<<"y^x^z";
if(p == 6) cout<<"y^z^x";
if(p == 7) cout<<"(y^x)^z";
if(p == 8) cout<<"(y^z)^x";
if(p == 9) cout<<"z^x^y";
if(p == 10) cout<<"z^y^x";
if(p == 11) cout<<"(z^x)^y";
if(p == 12) cout<<"(z^y)^x";
return 0;
}
E:给出b个序列A(b个序列都是一样的),你可以从中选b个数(一个序列选一个),然后把这b个数排成一个数字(比如你选了1,2,答案就是12),再Mod给定的数x,问有多少种选法使得最后的答案是k。(序列中的数<=9,k<=100,x<=100,k<x,b<=10^9,一个序列中不同位置的相同数算两种方案)。
首先想到转移方程:
F[i][c* 10 + num] += F[i-1][c] (当前选的是num这个数字)。
所以就可以矩阵乘法了,先预处理出数字i在之前的余数是c的情况下会转移到的状态(即(c * 10 + i)Mod p),然后矩阵中Dp[i][(c * 10 + i)Mod p] + 1就行了。
裸矩乘。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
#define Mod 1000000007
using namespace std;
int n,b,k,x,p,a;
struct Matrix {
long long val[101][101];
Matrix () {memset(val,0,sizeof(val));}
friend Matrix operator *(Matrix x,Matrix y) {
Matrix Ans;
for(int i = 0;i < p;i ++)
for(int j = 0;j < p;j ++)
for(int k = 0;k < p;k ++)
{
Ans.val[i][j] += x.val[i][k] * y.val[k][j];
Ans.val[i][j] %= Mod;
}
return Ans;
}
friend Matrix operator^(Matrix X,int Y) {
Matrix Ans;
for(int I = 0;I <= p - 1;I ++)
Ans.val[I][I] = 1;
while(Y > 0)
{
if(Y % 2 == 1) Ans = Ans * X;
X = X * X;
Y = Y / 2;
}
return Ans;
}
}A,B;
int main() {
scanf("%d%d%d%d",&n,&b,&k,&p);
for(int i = 1;i <= n;i ++)
{
scanf("%d",&a);
for(int j = 0;j < p;j ++)
{
B.val[j][(j * 10 + a) % p] ++;
}
}
A.val[0][0] = 1;
A = A * (B ^ b);
printf("%I64d",A.val[0][k]);
return 0;
}