CSP模拟19
CSP模拟19
T1 十年之约 CF1542C
我们要求
\[\sum_{i=1}^{n}f(i)
\]
其中 $$f(i)=k\Leftrightarrow\operatorname{lcm}(1,2,3,\dots,k-1)\mid{i},k\nmid{i}$$
我们先预处理 $$an_i=\operatorname{lcm}(1,2,3,\dots,i)$$
所以对于 \(i=1,2,3,\dots,n\),满足 \(an_{k-1}\mid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_{k-1}}\right\rfloor\) 个,满足 \(an_k\mid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_k}\right\rfloor\) 个。
利用容斥原理,满足 \(an_{k-1}\mid{i},an_{k}\nmid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_{k-1}}\right\rfloor-\left\lfloor\dfrac{i}{an_k}\right\rfloor\)
个。
这样,答案就是
\[\sum_{i=1}^{n}f_i=\sum_{an_i\le{n}}i\times\left(\left\lfloor\dfrac{i}{an_{k-1}}
\right\rfloor-\left\lfloor\dfrac{i}{an_k}\right\rfloor\right)\]
由于 \(\operatorname{lcm}\) 增长很快,所以查询是 \(O(log n)\) 的。
code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
int an[110],n,mod=1e9+7;
int lcm(int x,int y){
return x*y/__gcd(x,y);
}
signed main(){
an[0]=an[1]=1;
for(int i=2;i<=100;i++){
an[i]=lcm(an[i-1],i);
}
int t;
scanf("%lld",&t);
for(int i=1;i<=t;i++){
scanf("%lld",&n);
int ans=0;
for(int j=1;an[j]<=n;j++){
ans+=(j+1)*((n/an[j])-(n/an[j+1]))%mod;
ans%=mod;
}
printf("%lld\n",ans);
}
}
T2 可爱三小只 CF446B
直接贪心,用两个优先队列存储每行/列的和,取出最大的,减去代价后再放回,最后减去重复的部分即可。减去后可以是负数。
code
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
#define int long long
int n,m,k,p,ph[1000010],pl[1000010];
int a[1010][1010],ans=-1e17;
priority_queue<int>qh,ql;
signed main(){
scanf("%lld%lld%lld%lld",&n,&m,&k,&p);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lld",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
int sum=0;
for(int j=1;j<=m;j++){
sum+=a[i][j];
}
qh.push(sum);
}
for(int j=1;j<=m;j++){
int sum=0;
for(int i=1;i<=n;i++){
sum+=a[i][j];
}
ql.push(sum);
}
for(int i=1;i<=k;i++){
int x=qh.top();
qh.pop();
ph[i]=ph[i-1]+x;
x-=m*p;
qh.push(x);
}
for(int i=1;i<=k;i++){
int x=ql.top();
ql.pop();
pl[i]=pl[i-1]+x;
x-=n*p;
ql.push(x);
}
for(int i=0;i<=k;i++){
ans=max(ans,ph[i]+pl[k-i]-p*(k-i)*i);
}
printf("%lld",ans);
return 0;
}
T3 蛋糕塌了
T4 西安行
code
#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
const int mod=1e9+7;
int n,m,sta;
struct nod{
int k[10][10];
nod(){}
int * operator [] (int i){
return k[i];
}
nod(int x){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i==j)
k[i][j]=x;
else k[i][j]=0;
}
}
}
friend nod operator * (nod x,nod y){
nod c(0);
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int l=0;l<3;l++){
c[i][j]=(c[i][j]+1ll*x[i][l]*y[l][j])%mod;
}
}
}
return c;
}
}a,b,ans(1);
signed main(){
scanf("%lld%lld",&n,&m);
a[0][0]=2;a[0][1]=1;a[0][2]=1;
a[1][0]=2;a[1][1]=1;a[1][2]=0;
a[2][0]=1;a[2][1]=1;a[2][2]=1;
b[0][0]=1;b[0][1]=0;b[0][2]=0;
b[1][0]=2;b[1][1]=1;b[1][2]=0;
b[2][0]=1;b[2][1]=1;b[2][2]=1;
for(int i=1;i<=m;i++){
int x;
scanf("%lld",&x);
int id=x-sta-1;
nod c=a;
while(id){
if(id&1) ans=c*ans;
c=c*c;
id>>=1;
}
ans=b*ans;
sta=x;
}
int id=n-sta-1;
nod c=a;
while(id){
if(id&1) ans=c*ans;
c=c*c;
id>>=1;
}
ans=b*ans;
printf("%lld\n",ans[2][0]);
return 0;
}