layout: post
title: Codeforces Round 257 (Div. 2)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces
A - Jzzhu and Children (签到)
题意
模拟给N个孩子发糖一次发M个 每个孩子需要a[i]个糖 如果给的糖满足孩子的需要孩子就会走,不满足就会到队伍最后 问你最后走的孩子编号
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
queue<pair<int,int> >pq;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
int a;
cin>>a;
pq.push({a,i});
}
int last=-1;
while(!pq.empty()){
int aa=pq.front().first;
last=pq.front().second;
pq.pop();
aa-=m;
if(aa>0)pq.push({aa,last});
}
cout<<last;
return 0;
}
B - Jzzhu and Sequences ( 矩阵快速幂)
题意
a[1]=x,a[2]=y,a[i]=a[i+1]+a[i-1]
让你求a[n]
思路
可以发现a[i]=a[i-1]-a[i-2];
然后就可以矩阵快速幂了,或者可以多推几项发现这个数论是6个一循环
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
typedef vector<ll>vec;
typedef vector<vec>mat;
mat mul(mat& A,mat &B){
mat C(A.size(),vec(B[0].size()));
for(int i=0;i<A.size();i++)
for(int k=0;k<B.size();k++)
if(A[i][k])
for(int j=0;j<B[0].size();j++)
C[i][j]=(C[i][j]+A[i][k]*B[k][j]%mod+mod)%mod;
return C;
}
mat Pow(mat A,ll n){
mat B(A.size(),vec(A.size()));
for(int i=0;i<A.size();i++)B[i][i]=1;
for(;n;n>>=1,A=mul(A,A))
if(n&1)B=mul(B,A);
return B;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
ll x,y,n;
cin>>x>>y>>n;
x=(x+mod)%mod;y=(y+mod)%mod;
if(n==1)cout<<x,exit(0);
if(n==2)cout<<y,exit(0);
mat a=mat(2,vec(2));
a[0][0]=1;a[0][1]=-1;
a[1][0]=1;a[1][1]=0;
a=Pow(a,n-2);
mat b=mat(2,vec(1));
b[0][0]=y;
b[1][0]=x;
a=mul(a,b);
cout<<(a[0][0]+mod)%mod<<endl;
return 0;
}
C - Jzzhu and Chocolate (思维)
题意
给你一个矩形巧克力
你可以横切竖切,但是只能在巧克力的内边并且不能破坏巧克力的内部
让你切K刀 使得最小面积最大
思路
可以发现如果K>n+m-2是不能完全切完
然后贪心的做法就是这K刀全部切同一个方向,然后不足K到的切其他方向
为什么可以全部切同一方向呢,假设我们现在有一个4×6的巧克力 我们现在在切一竖刀 变成2×6=12的巧克力 如果我们切横刀变成4乘3=12的巧克力,那么如果我们两刀都切横
1×6=6 如果两刀交叉切 变成2乘3=6的巧克力
如果两道都竖切,变成4乘2=8的巧克力 明显答案更优
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
ll n,m,k;
cin>>n>>m>>k;
ll cancut=n+m-2;
ll ans=0;
if(k>cancut)cout<<-1,exit(0);
else{
if(k>=n)ans=max(ans,1LL*m/(k-n+2LL));
if(k>=m)ans=max(ans,1LL*n/(k-m+2LL));
if(k<n)ans=max(ans,1LL*m*(n/(k+1LL)));
if(k<m)ans=max(ans,1LL*n*(m/(k+1LL)));
}
cout<<ans<<endl;
return 0;
}
D - Jzzhu and Cities (最短路)
题意
给你一个无向图,结点1为首都
有m条铁路 每条铁路有距离 同时有K条直通首都的航线 同时也有距离
现在想要关掉最多航线,同时使得首都到其他点的最短路不变
思路
一开始以为是求个最小生成树....
后来发现直接求个最短路 然后航线也参与最短路的求解中,有其他的路线更新了这个航线的距离就可以把这个航线给去掉了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m,k;
vector<pii>G[maxn];
ll d[maxn];
int vis[maxn];
int need[maxn];
int dij(){
fill(d,d+maxn,1e18);
d[1]=0;
queue<int>pq;
vis[1]=1;
pq.push(1);
for(int i=1;i<=k;i++){
int u,x;
cin>>u>>x;
if(d[u]>x){
d[u]=x;need[u]=1;
if(vis[u]==0){
pq.push(u);
vis[u]=1;
}
}
}
while(!pq.empty()){
int u=pq.front();pq.pop();
vis[u]=0;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].first,x=G[u][i].second;
if(d[v]>=d[u]+x&&need[v])need[v]=0;
if(d[v]>d[u]+x){
d[v]=d[u]+x;
if(vis[v]==0){
vis[v]=1;
pq.push(v);
}
}
}
}
for(int i=1;i<=n;i++){
k-=need[i];
}
return k;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v,x;
cin>>u>>v>>x;
G[u].push_back({v,x});
G[v].push_back({u,x});
}
cout<<dij()<<endl;
return 0;
}
E - Jzzhu and Apples (大模拟+素数)
题意
给N个苹果编号1-n 然后两两分组,并且同一组的两个苹果的编号不能互质
让你求出最大分组数和分组情况
思路
首先偶数肯定是可以分组的
然后我们就考虑奇数
发现奇数 能匹配是需要有倍数关系的,然后我们就枚举每个奇数 发现复杂度有点爆炸 其实我们可以直接枚举素数,然后把素数和他的倍数放在一起,如果是偶数个那就直接分组了
如果是奇数个,那就最好把其中一个偶数拿出来 其他的分组,这样处理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int vis[maxn];
int prime[maxn];
bool check[maxn];
int tot;
void init(int n){
tot=0;
for(int i=2;i<=n;i++){
if(!check[i]){
prime[++tot]=i;
}
for(int j=1;j<=tot;j++){
if(i*prime[j]>n)break;
check[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
vector<int>L,R;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin>>n;
init(n);
for(int i=2;i<=tot;i++){
vector<int>s;
int x=prime[i];
for(int j=x;j<=n;j+=x)
if(!vis[j])s.push_back(j);
int cnt=s.size();
if(cnt&1){
for(int j=0;j<cnt;j++){
if(s[j]%2==0){
s.erase(s.begin()+j);break;
}
}
}
cnt=s.size();
for(int j=1;j<cnt;j+=2){
vis[s[j-1]]=1;vis[s[j]]=1;
L.push_back(s[j-1]);R.push_back(s[j]);
}
}
vector<int>even;
for(int i=2;i<=n;i+=2)if(!vis[i])even.push_back(i);
int cnt=even.size();
for(int i=1;i<cnt;i+=2)L.push_back(even[i-1]),R.push_back(even[i]);
cout<<L.size()<<endl;
for(int i=0;i<L.size();i++)
cout<<L[i]<<" "<<R[i]<<endl;
return 0;
}