题目链接
题意:
n 个 数 , 进 行 乘 法 和 加 法 n个数,进行乘法和加法 n个数,进行乘法和加法
要 求 乘 法 和 加 法 的 次 数 一 样 多 要求乘法和加法的次数一样多 要求乘法和加法的次数一样多
题解:
选 n / 2 个 小 的 进 行 相 加 选n/2个小的进行相加 选n/2个小的进行相加
相 加 之 后 乘 后 n / 2 个 大 的 即 可 相加之后乘后n/2个大的即可 相加之后乘后n/2个大的即可
( 题 目 给 出 n 为 偶 数 , 我 当 时 没 看 见 , 代 码 考 虑 了 奇 数 情 况 ) (题目给出n为偶数,我当时没看见,代码考虑了奇数情况) (题目给出n为偶数,我当时没看见,代码考虑了奇数情况)
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double,double> pdd;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
ll a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
ll ans=0;
int i=1;
if(n&1)i++;
for(;i<=n;i++){
if(i<=(n+1)/2)ans=(ans+a[i])%mod;
else ans=ans*a[i]%mod;
}
cout<<ans;
return 0;
}
题意:
n 个 组 , 每 组 m 个 数 n个组,每组m个数 n个组,每组m个数
一 组 的 权 值 为 该 组 数 的 乘 积 一组的权值为该组数的乘积 一组的权值为该组数的乘积
求 最 大 权 值 m o d 1 e 9 + 7 求最大权值mod~1e9+7 求最大权值mod 1e9+7
每 个 数 都 为 k 的 非 负 整 数 次 幂 每个数都为k的非负整数次幂 每个数都为k的非负整数次幂
题解:
由 于 取 余 了 , 所 以 没 法 比 较 大 小 由于取余了,所以没法比较大小 由于取余了,所以没法比较大小
这 个 时 候 最 后 一 句 话 很 关 键 这个时候最后一句话很关键 这个时候最后一句话很关键
由 于 有 最 后 一 句 话 , m 个 数 就 可 以 化 成 由于有最后一句话,m个数就可以化成 由于有最后一句话,m个数就可以化成
k a 1 , k a 2 , … … , k a n k^{a_1},k^{a_2},……,k^{a_n} ka1,ka2,……,kan
那 么 这 些 数 相 乘 就 是 把 他 们 的 指 数 相 加 那么这些数相乘就是把他们的指数相加 那么这些数相乘就是把他们的指数相加
所 以 直 接 把 每 一 组 全 部 化 成 k 的 幂 形 式 , 指 数 相 加 比 大 小 所以直接把每一组全部化成k的幂形式,指数相加比大小 所以直接把每一组全部化成k的幂形式,指数相加比大小
最 后 用 快 速 幂 算 出 答 案 最后用快速幂算出答案 最后用快速幂算出答案
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double,double> pdd;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
ll n,m,k,p;
ll Pow(ll a, ll b){
ll ans = 1;
while(b > 0){
if(b & 1){
ans = ans * a % p;
}
a = a * a % p;
b >>= 1;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>m>>k>>p;
ll ans=0;
if(k==1){cout<<1;return 0;}
for(int i=1;i<=n;i++){
ll tmp=0;
for(int j=1;j<=m;j++){
ll x;
cin>>x;
x/=k;
while(x)x/=k,tmp++;
}
ans=max(ans,tmp);
}
cout<<Pow(k,ans);
return 0;
}
题意:
二 维 平 面 上 有 n 个 点 二维平面上有n个点 二维平面上有n个点
初 始 位 置 为 ( 0 , 0 ) , 可 以 选 择 任 意 一 个 非 当 前 位 置 给 出 的 点 初始位置为(0,0),可以选择任意一个非当前位置给出的点 初始位置为(0,0),可以选择任意一个非当前位置给出的点
把 这 个 点 和 初 始 位 置 连 成 直 线 , 可 以 到 达 直 线 中 的 任 意 一 个 位 置 把这个点和初始位置连成直线,可以到达直线中的任意一个位置 把这个点和初始位置连成直线,可以到达直线中的任意一个位置
这 个 位 置 的 坐 标 可 以 不 是 整 数 这个位置的坐标可以不是整数 这个位置的坐标可以不是整数
询 问 q 次 , 最 少 多 少 次 到 达 ( x i , y i ) 询问q次,最少多少次到达(x_i,y_i) 询问q次,最少多少次到达(xi,yi)
题解:
把 样 例 画 一 遍 就 会 发 现 , 其 实 最 多 也 只 需 要 3 次 到 达 把样例画一遍就会发现,其实最多也只需要3次到达 把样例画一遍就会发现,其实最多也只需要3次到达
然 后 直 接 对 每 个 答 案 进 行 分 析 然后直接对每个答案进行分析 然后直接对每个答案进行分析
如 果 ( 0 , 0 ) 和 某 个 点 的 直 线 直 接 能 到 ( x i , y i ) 如果(0,0)和某个点的直线直接能到(x_i,y_i) 如果(0,0)和某个点的直线直接能到(xi,yi)
那 就 直 接 答 案 为 1 , 这 个 就 需 要 用 到 斜 率 那就直接答案为1,这个就需要用到斜率 那就直接答案为1,这个就需要用到斜率
但 为 了 防 止 卡 精 度 考 虑 用 s e t 和 g c d 但为了防止卡精度考虑用set和gcd 但为了防止卡精度考虑用set和gcd
对 每 个 点 ( a i , b i ) 换 成 ( a i / g c d ( a , b ) , b i / g c d ( a , b ) ) 对每个点(a_i,b_i)换成(a_i/gcd(a,b),b_i/gcd(a,b)) 对每个点(ai,bi)换成(ai/gcd(a,b),bi/gcd(a,b))
这 样 既 可 以 表 示 斜 率 , 又 可 以 防 止 卡 精 度 这样既可以表示斜率,又可以防止卡精度 这样既可以表示斜率,又可以防止卡精度
如 果 询 问 的 时 候 有 这 样 的 点 存 在 , 说 明 答 案 为 1 如果询问的时候有这样的点存在,说明答案为1 如果询问的时候有这样的点存在,说明答案为1
然 后 开 始 分 析 不 存 在 的 情 况 然后开始分析不存在的情况 然后开始分析不存在的情况
首 先 考 虑 − 1 , 根 本 到 不 了 首先考虑-1,根本到不了 首先考虑−1,根本到不了
如 果 所 有 点 到 ( 0 , 0 ) 都 是 共 线 的 , 那 么 肯 定 到 不 了 如果所有点到(0,0)都是共线的,那么肯定到不了 如果所有点到(0,0)都是共线的,那么肯定到不了
这 种 时 候 只 有 一 种 斜 率 这种时候只有一种斜率 这种时候只有一种斜率
如 果 图 中 有 超 过 2 个 点 , 因 为 点 不 重 复 如果图中有超过2个点,因为点不重复 如果图中有超过2个点,因为点不重复
总 可 以 从 ( 0 , 0 ) 和 一 个 点 连 线 到 达 终 点 和 某 个 点 的 连 线 上 总可以从(0,0)和一个点连线到达终点和某个点的连线上 总可以从(0,0)和一个点连线到达终点和某个点的连线上
这 样 就 需 要 2 次 , 答 案 就 为 2 这样就需要2次,答案就为2 这样就需要2次,答案就为2
然 后 考 虑 3 次 的 情 况 , 这 个 时 候 只 有 2 个 点 的 情 况 然后考虑3次的情况,这个时候只有2个点的情况 然后考虑3次的情况,这个时候只有2个点的情况
可 以 发 现 , 如 果 这 ( 0 , 0 ) 到 一 个 点 和 ( x i , y i ) 到 另 一 个 点 平 行 可以发现,如果这(0,0)到一个点和(x_i,y_i)到另一个点平行 可以发现,如果这(0,0)到一个点和(xi,yi)到另一个点平行
就 需 要 多 去 走 一 次 , 找 相 交 的 时 刻 , 这 时 候 就 需 要 3 就需要多去走一次,找相交的时刻,这时候就需要3 就需要多去走一次,找相交的时刻,这时候就需要3
其 实 就 是 一 个 平 行 四 边 形 , 并 且 对 角 为 ( 0 , 0 ) 和 ( x i , y i ) 其实就是一个平行四边形,并且对角为(0,0)和(x_i,y_i) 其实就是一个平行四边形,并且对角为(0,0)和(xi,yi)
除 此 之 外 都 是 2 的 情 况 了 除此之外都是2的情况了 除此之外都是2的情况了
但 是 这 道 题 需 要 注 意 的 是 , 二 维 坐 标 的 点 可 能 给 出 ( 0 , 0 ) 但是这道题需要注意的是,二维坐标的点可能给出(0,0) 但是这道题需要注意的是,二维坐标的点可能给出(0,0)
但 其 实 这 个 点 是 没 有 用 的 , 如 果 可 以 走 一 开 始 就 用 了 但其实这个点是没有用的,如果可以走一开始就用了 但其实这个点是没有用的,如果可以走一开始就用了
否 则 如 果 再 想 用 ( 0 , 0 ) 至 少 需 要 3 步 , 那 就 算 不 用 ( 0 , 0 ) 也 可 以 到 达 了 否则如果再想用(0,0)至少需要3步,那就算不用(0,0)也可以到达了 否则如果再想用(0,0)至少需要3步,那就算不用(0,0)也可以到达了
所 以 直 接 把 ( 0 , 0 ) 去 掉 不 要 影 响 最 后 的 判 断 所以直接把(0,0)去掉不要影响最后的判断 所以直接把(0,0)去掉不要影响最后的判断
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double,double> pdd;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
ll a[maxn],xx[maxn],yy[maxn];
ll b[maxn];
bool ok(ll x,ll y){
if((xx[1]-x)*yy[2]-(yy[1]-y)*xx[2])return 0;
if((xx[2]-x)*yy[1]-(yy[2]-y)*xx[1])return 0;
return 1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,q;
cin>>n>>q;
set<pii> s;
for(int i=1;i<=n;i++){
cin>>xx[i]>>yy[i];
if(!xx[i]&&!yy[i]){i--,n--;continue;}
int tmp=__gcd(xx[i],yy[i]);
s.insert(mp(xx[i]/tmp,yy[i]/tmp));
}
while(q--){
ll x,y;
cin>>x>>y;
if(!x&&!y){cout<<0<<endl;continue;}
int tmp=__gcd(x,y);
bool f=0;
if(ok(x,y))f=1;
x/=tmp,y/=tmp;
if(s.count(mp(x,y)))cout<<1<<endl;
else if(s.size()<=1)cout<<-1<<endl;
else {
if(n>2)cout<<2<<endl;
else{
if(f)cout<<3<<endl;
else cout<<2<<endl;
}
}
}
return 0;
}
题意:
给 一 个 数 n , 把 n 拆 成 几 个 数 , 这 几 个 数 的 和 为 n 给一个数n,把n拆成几个数,这几个数的和为n 给一个数n,把n拆成几个数,这几个数的和为n
使 得 这 个 数 的 子 序 列 ( 包 括 空 序 列 , l c m 为 1 ) 中 有 尽 量 多 的 l c m 使得这个数的子序列(包括空序列,lcm为1)中有尽量多的lcm 使得这个数的子序列(包括空序列,lcm为1)中有尽量多的lcm
求 出 这 个 最 大 值 m o d 1 e 9 + 7 求出这个最大值 mod~1e9+7 求出这个最大值mod 1e9+7
题解:
拆 出 的 数 首 先 一 定 是 不 同 的 , 如 果 重 复 出 现 不 会 增 加 l c m 数 量 拆出的数首先一定是不同的,如果重复出现不会增加lcm数量 拆出的数首先一定是不同的,如果重复出现不会增加lcm数量
反 而 会 浪 费 n 的 一 部 分 值 反而会浪费n的一部分值 反而会浪费n的一部分值
每 个 数 都 拆 成 质 数 的 幂 每个数都拆成质数的幂 每个数都拆成质数的幂
并 且 质 数 的 幂 是 从 小 到 大 进 行 选 择 并且质数的幂是从小到大进行选择 并且质数的幂是从小到大进行选择
因 为 如 果 某 一 个 数 是 b i a p ∗ b j a q 因为如果某一个数是b_i^{a_p}*b_j^{a_q} 因为如果某一个数是biap∗bjaq
你 完 全 可 以 把 他 拆 成 b i a p 和 b j a q 你完全可以把他拆成b_i^{a_p}和b_j^{a_q} 你完全可以把他拆成biap和bjaq
由 于 基 本 不 等 式 之 类 的 推 论 , 所 以 相 加 一 定 比 相 乘 花 费 小 由于基本不等式之类的推论,所以相加一定比相乘花费小 由于基本不等式之类的推论,所以相加一定比相乘花费小
甚 至 贡 献 可 能 比 相 乘 大 甚至贡献可能比相乘大 甚至贡献可能比相乘大
所 以 就 成 了 一 个 选 素 数 幂 的 过 程 和 记 录 贡 献 所以就成了一个选素数幂的过程和记录贡献 所以就成了一个选素数幂的过程和记录贡献
先 进 行 素 数 筛 , 然 后 就 可 以 用 背 包 进 行 计 算 最 大 贡 献 先进行素数筛,然后就可以用背包进行计算最大贡献 先进行素数筛,然后就可以用背包进行计算最大贡献
因 为 出 现 的 这 样 出 现 的 l c m 都 是 不 会 重 复 的 因为出现的这样出现的lcm都是不会重复的 因为出现的这样出现的lcm都是不会重复的
所 以 直 接 和 之 前 的 l c m 相 乘 就 是 新 的 贡 献 所以直接和之前的lcm相乘就是新的贡献 所以直接和之前的lcm相乘就是新的贡献
但 是 这 个 结 果 要 进 行 取 余 , 就 没 法 比 大 小 了 但是这个结果要进行取余,就没法比大小了 但是这个结果要进行取余,就没法比大小了
所 以 就 用 l o g 进 行 记 录 大 小 , l o g 相 加 即 里 面 的 数 相 乘 所以就用log进行记录大小,log相加即里面的数相乘 所以就用log进行记录大小,log相加即里面的数相乘
而 且 l o g 可 以 保 证 大 小 在 范 围 内 而且log可以保证大小在范围内 而且log可以保证大小在范围内
最 后 找 到 最 大 值 即 可 最后找到最大值即可 最后找到最大值即可
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, ll> pll;
typedef pair<double,double> pdd;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
int prime[maxn];
bool isprime[maxn];
int num=0;
void Prime(int n){
memset(isprime,true,sizeof(isprime));
for(int i=2;i<=n;i++){
if(isprime[i]) prime[++num]=i;
for(int j=1;j<=num;j++){
if(i*prime[j]>maxn) break;
isprime[i*prime[j]]=false;
if(i%prime[j]==0) break;
}
}
}
pll dp[maxn] ;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
Prime(100000);
int n;
ll sum=0;pll ans=mp(0,1);
cin>>n;
dp[0]=mp(0,1);
for(int i=1;i<=n;i++){
for(int j=n;j>=1;j--){
ll x,y,k=1;
x=y=prime[i];
while(x<=j){
dp[j]=max(dp[j],mp(dp[j-x].fi+log2(k+1),dp[j-x].se*(k+1)%mod));
y*=prime[i],k++,x+=y;
}
ans=max(ans,dp[j]);
}
sum+=prime[i];
if(sum>n)break;
}
cout<<ans.se;
return 0;
}
题意:
共 有 n 个 点 , 第 i 个 点 的 点 权 为 a i , 还 有 一 个 b i 共有n个点,第i个点的点权为a_i,还有一个b_i 共有n个点,第i个点的点权为ai,还有一个bi
每 多 一 次 经 过 第 i 个 点 点 权 就 要 加 b i 每多一次经过第i个点点权就要加b_i 每多一次经过第i个点点权就要加bi
即 第 k 次 经 过 i 节 点 的 权 值 为 a i + ( k − 1 ) ∗ b i 即第k次经过i节点的权值为a_i + (k - 1)*b_i 即第k次经过i节点的权值为ai+(k−1)∗bi
其 中 有 m 条 路 从 u i 到 v i 其中有m条路从u_i到v_i 其中有m条路从ui到vi
有 q 个 x i , y i 选 择 q 对 从 x i 到 y i , 代 价 为 路 径 点 权 和 有q个x_i,y_i选择q对从x_i到y_i,代价为路径点权和 有q个xi,yi选择q对从xi到yi,代价为路径点权和
求 最 小 的 代 价 求最小的代价 求最小的代价
题解:
q 个 x i 到 任 一 q 个 里 选 一 个 的 y i q个x_i到任一q个里选一个的y_i q个xi到任一q个里选一个的yi
直 接 就 可 以 考 虑 一 下 费 用 流 了 直接就可以考虑一下费用流了 直接就可以考虑一下费用流了
对 每 个 点 进 行 裂 点 , 并 且 由 于 可 能 走 q 次 对每个点进行裂点,并且由于可能走q次 对每个点进行裂点,并且由于可能走q次
所 有 对 每 个 点 裂 点 后 建 q 个 边 , 每 个 边 的 流 量 为 1 , 费 用 变 化 的 点 权 所有对每个点裂点后建q个边,每个边的流量为1,费用变化的点权 所有对每个点裂点后建q个边,每个边的流量为1,费用变化的点权
然 后 把 每 条 路 进 行 相 连 , 费 用 为 0 , 流 量 i n f 然后把每条路进行相连,费用为0,流量inf 然后把每条路进行相连,费用为0,流量inf
然 后 把 x i 连 接 到 超 级 源 点 , y i 连 接 到 超 级 汇 点 费 用 为 0 , 流 量 为 1 然后把x_i连接到超级源点,y_i连接到超级汇点费用为0,流量为1 然后把xi连接到超级源点,yi连接到超级汇点费用为0,流量为1
最 后 跑 出 费 用 流 即 可 最后跑出费用流即可 最后跑出费用流即可
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double,double> pdd;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
//spfa
int n,m,s,t,N;
struct edge{
ll v,nx,f,w;
}e[1000010];
int cnt,maxflow,maxcost;
ll head[maxn],dis[maxn],pre[maxn],maxf[maxn];
bool inq[maxn];
void add(int u,int v,int f,int w){
e[cnt]={v,head[u],f,w};
head[u]=cnt++;
e[cnt]={u,head[v],0,-w};
head[v]=cnt++;
}
void init(){
for(int i=0;i<=N;i++)
head[i]=-1;
maxflow=maxcost=cnt=0;
}
bool spfa(){
for(int i=0;i<=N;i++)dis[i]=inf;
queue<int> q;
q.push(s);
dis[s]=0,inq[s]=1,maxf[s]=inf;
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=0;
for(int i=head[u];i!=-1;i=e[i].nx){
int v=e[i].v;
if(e[i].f&&dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
pre[v]=i;
maxf[v]=min(maxf[u],e[i].f);
if(!inq[v])inq[v]=1,q.push(v);
}
}
}
return dis[t]<inf;
}
void MCMF(){
while(spfa()){
int u=t,i;
while(u!=s){
i=pre[u];
e[i].f-=maxf[t];
e[i^1].f+=maxf[t];
u=e[i^1].v;
}
maxflow+=maxf[t];
maxcost+=dis[t]*maxf[t];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m,q;
cin>>n>>m>>q;
N=t=2*n+1;
init();
for(int i=1;i<=n;i++){
ll a,b;
cin>>a>>b;
for(int j=0;j<q;j++)
add(i,i+n,1,a+j*b);
}
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
add(u+n,v,inf,0);
add(v+n,u,inf,0);
}
for(int i=1;i<=q;i++){
int x;cin>>x;
add(s,x,1,0);
}
for(int i=1;i<=q;i++){
int y;cin>>y;
add(y+n,t,1,0);
}
MCMF();
cout<<maxcost;
return 0;
}