10.6 Morning
居然拿到了rk5,还get到了qbxt的小恩小惠
今天真是欧啊
Problem A.hi
【题目描述】
LYK最近学了最长子序列。发现这玩意儿太简单了。
它发明了属于自己的子序列。
即:给定n个数ai,选择其中若干个数按顺序形成子序列,要求满足这个子序列中任意相邻两个数做位运算与运算后都不等于0。(例如2&4=0,1&3=1)
LYK想知道这个子序列最长有多长。
【输入描述】
第一行一个数n。
接下来一行n个数表示ai。
【输出描述】
一个数表示这个子序列最长多长。
【输入输出样例】
【input】
3
1 2 3
【output】
2
【数据范围】
对于20%的数据n<=10。
对于60%的数据n<=1000。
对于100%的数据1<=n<=100000, 0<=ai<=10^9。
zhw蜜汁题解:f[x] 表示二进制意义下第x位为1的数结尾的最长子序列是多少
dp[i] 以a[i]结尾的最长子序列是多少
枚举所有x,若a[i]&(1<<x),就可以从f[x]+1转移得到dp[i]。最终用dp[i]去更新f。
【代码实现】
博主闲的没事在考场上写的20分暴力
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<algorithm>
#define N 100001
int n,a[N],p,q,ans;
int main()
{
freopen("hi.in","r",stdin);
freopen("bl.out","w",stdout);
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
for(register int i=1;i<=(1<<n)-1;i++)
{
p=(1<<29)-1;q=0;
for(register int j=1;j<=n;j++)
if((i&(1<<(j-1)))&&(p&a[j]))
{
p=a[j];
q++;
}
ans=std::max(ans,q);
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
博主没事在考场上写的60分暴力
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<algorithm>
#define N 100001
int n,a[N],dp[N],ans;
int main()
{
freopen("hi.in","r",stdin);
freopen("hi.out","w",stdout);
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i]=1;
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<i;j++)
if(a[i]&a[j]) dp[i]=std::max(dp[i],dp[j]+1);
ans=std::max(ans,dp[i]);
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
博主在考场上闲的没事写的100分正解
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<algorithm>
#define N 100001
int n,dp[N],ans,f[40];
long long a[N];
int main()
{
freopen("hi.in","r",stdin);
freopen("hi.out","w",stdout);
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(register int i=1;i<=n;i++)
{
for(register long long j=0;j<=32;j++)
if(a[i]&(1<<j)) dp[i]=std::max(dp[i],f[j]+1);
for(register long long j=0;j<=32;j++)
if(a[i]&(1<<j)) f[j]=std::max(f[j],dp[i]);
ans=std::max(ans,dp[i]);
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
Problem B. haha
【题目描述】
LYK在一个K维空间中。
它有n条飞船,第i条飞船所在的位置是{s[i][1],s[i][2],...,s[i][K]}。
它想利用这n条飞船去摧毁水晶,这个水晶是一个中心点在{c1,c2,...,cK}且半径为r的范数球。
所谓半径为r的范数球是指:任意距离这个水晶中心点的曼哈顿距离(每维坐标差的绝对值的和)小于等于r的点,都处于这个水晶中。
你想用这些飞船攻击这个水晶,但是进攻的能量会随着距离衰减,因此对于每条飞船,你都需要找一个水晶的位置,使得离这条飞船的欧式距离(每维坐标差的平方和再开根)最短。
LYK保证这n条飞船都不在水晶所在的范数球中。
LYK想知道这n个最短的欧氏距离之和是多少。
【输入描述】
一行两个数n,K。表示有n条飞船,LYK在K维空间中。
接下来一行一个数r。
接下来一行K个数,表示这个水晶的中心点。
接下来n行,每行K个数,表示每条飞船所在的位置。
【输出描述】
一个数表示所有欧氏距离之和,答案保留3位小数。(四舍五入)
【输入输出样例】
【input】
2 2
1
0 0
1 1
1 3
【output】
2.943
【数据范围】
对于30%的数据K=1。
对于60%的数据K<=2。
对于100%的数据1<=K<=50,1<=n<=100, 1<=r<=1000,-1000<=s[x][y],c[x]<=1000。输入的数都是整数。
zhw蜜汁题解:
一开始把所有维度减去水晶中心的值。因此,我们可以默认水晶中心在{0,0,...}
对于一艘飞船,它的每个维度取它绝对值。
所有维度都是正整数,且要半径为r,中心在原点的范数球
把所有维度减去一个ai(不能成为负数),最终当所有维度之和=r时,就能攻击到范数球了。
最小化代价 = sqrt(sum{ai^2})
先将所有维度从小到大排序。
1 2 4 3 0 1 3
0 0.5 2.5
存在一个阈值x, 使得前x维,完全贴近中心, x+1~K维,每一维减去一个相同的值
【代码实现】
30分代码
#include<iostream>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
using namespace std;
int k,n;
double r;
double pos[1010][110];
int main()
{
freopen("haha.in","r",stdin);
freopen("haha.out","w",stdout);
double ans=0;
cin>>n>>k>>r;
for(int i=0;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
cin>>pos[i][j];
}
}
if(k==1)
{
double x1=pos[0][1]-r;
double x2=pos[0][1]+r;
for(int i=1;i<=n;i++)
{
double a1=x1-pos[i][1];
double a2=x2-pos[i][1];
if(a1<0) a1*=(-1);
if(a2<0) a2*=(-1);
if(a1<a2) ans+=a1;
else ans+=a2;
}
cout<<setprecision(3)<<fixed<<ans;
}
return 0;
}
博主在考场上闲的没事写的60分代码
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k,a,kk,r,yd[60],zb[110][60];
double nx,ans=0.0;
double calc_ou(double x1,double y1,double x2,double y2)
{
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
void baogank2()
{
for(register int i=1;i<=n;++i)
{
zb[i][1]-=yd[1],zb[i][2]-=yd[2];
if(zb[i][1]==0||zb[i][2]==0)
{
ans+=max(abs(zb[i][1]),abs(zb[i][2]))-r;
continue;
}
if(zb[i][1]>0&&zb[i][2]>0)//1
{
a=1;
kk=zb[i][2]-zb[i][1];
nx=(double)(r-kk)/(double)(a+1);
if(nx>=(double)0&&nx<=r)ans+=calc_ou(nx,nx+kk,zb[i][1],zb[i][2]);
else ans+=min(calc_ou(0,r,zb[i][1],zb[i][2]),calc_ou(r,0,zb[i][1],zb[i][2]));
continue;
}
if(zb[i][1]>0&&zb[i][2]<0)//4
{
a=-1;
kk=zb[i][2]+zb[i][1];
nx=(double)(-r-kk)/(double)(a-1);
if(nx>=(double)0&&nx<=r)ans+=calc_ou(nx,-1*nx+kk,zb[i][1],zb[i][2]);
else ans+=min(calc_ou(0,-1*r,zb[i][1],zb[i][2]),calc_ou(r,0,zb[i][1],zb[i][2]));
continue;
}
if(zb[i][1]<0&&zb[i][2]>0)
{
a=-1;
kk=zb[i][2]+zb[i][1];
nx=(double)(r-kk)/(double)(a-1);
if(nx<=(double)0&&nx>=-1.0*r)ans+=calc_ou(nx,-1*nx+kk,zb[i][1],zb[i][2]);
else ans+=min(calc_ou(0,r,zb[i][1],zb[i][2]),calc_ou(-1*r,0,zb[i][1],zb[i][2]));
continue;
}
if(zb[i][1]<0&&zb[i][2]<0)
{
a=1;
kk=zb[i][2]-zb[i][1];
nx=(double)(-r-kk)/(double)(a+1);
if(nx<=(double)0&&nx>=-1.0*r)ans+=calc_ou(nx,nx+kk,zb[i][1],zb[i][2]);
else ans+=min(calc_ou(0,-1*r,zb[i][1],zb[i][2]),calc_ou(-1*r,0,zb[i][1],zb[i][2]));
continue;
}
}
}
int cx;
void baogank1()
{
for(register int i=1;i<=n;++i)
{
zb[i][1]-=yd[1];
cx=zb[i][1];
if(cx>0)
{
ans+=cx-r;
continue;
}
if(cx<0)
{
ans+=-r-cx;
continue;
}
}
}
int main()
{
freopen("haha.in","r",stdin);
freopen("haha.out","w",stdout);
scanf("%d%d%d",&n,&k,&r);
for(register int i=1;i<=k;++i)scanf("%d",&yd[i]);
for(register int i=1;i<=n;++i)
for(register int j=1;j<=k;++j)
scanf("%d",&zb[i][j]);
if(k==2) baogank2();
if(k==1) baogank1();
printf("%.3lf",ans);
return 0;
}
100分std
#include <bits/stdc++.h>
using namespace std;
int a[105],b[105],n,m,r,X,T,i,j,sum,d[105],h[105];
double c[105],ans,ANS;
struct node {int x,y;} t[105];
int cmp(node i,node j) {return i.x<j.x;}
double ANSS;
int main()
{
freopen("haha.in","r",stdin);
freopen("haha.out","w",stdout);
T=1;
while (T--)
{
scanf("%d%d",&n,&m);
scanf("%d",&r);
for (i=1; i<=m; i++) scanf("%d",&a[i]);
while (n--)
{
for (i=1; i<=m; i++) {scanf("%d",&t[i].x); t[i].x=abs(t[i].x-a[i]); t[i].y=i;}
sort(t+1,t+m+1,cmp);
for (i=1; i<=m; i++) b[i]=t[i].x;
ANS=1000000000;
for (i=0; i<m; i++)
{
ans=0;
for (j=1; j<=i; j++) ans+=b[j]*b[j];
sum=0;
for (j=i+1; j<=m; j++) sum+=b[j];
if ((double)(sum-r)/(m-i)>b[i+1]) continue;
ans+=((double)(sum-r)*(sum-r)/(m-i));
if (ans<ANS) {ANS=ans; X=i;}
}
ANSS+=sqrt(ANS);
}
}
printf("%.3f\n",ANSS);
return 0;
}
Problem C. math
LYK看到一个题:
计算(3+2√2)^n的整数部分对1000000007取模后的结果。 LYK不会做,来问你。你帮他做出来就能获得100分。
【输入格式】
一行一个数n。
【输出格式】
一个数答案。
【输入输出样例】
【input】
2
【output】
33
【数据范围】
对于20%的数据n<=4。
对于40%的数据n<=10。
对于60%的数据n<=100。
对于80%的数据n<=10^7。
对于100%的数据1<=n<=10^9。
zhw蜜汁题解
f[i]表示 (3+2sqrt2)^i + (3-2sqrt2)^i ans = f[n] % 1e9+7 - 1
f[i]*f[j]
((3+2sqrt2)^i + (3-2sqrt2)^i) * ((3+2sqrt2)^j + (3-2sqrt2)^j) (i>j)
(3+2sqrt2)^(i+j) + (3+2sqrt2)^(i-j) + (3-2sqrt2)^(i-j)+ (3-2sqrt2)^(i+j)
f[i]*f[j] = f[i+j] + f[i-j]
另j=1
f[i]*f[1] = f[i+1] + f[i-1]
f[i+1] = 6 * f[i] - f[i-1] 矩阵快速幂
① f[n] 尽可能把n分成均匀两份 n是偶数: f[n]=f[n/2]*f[n/2]-2
n是奇数: f[n]=f[n/2]*f[n/2+1]-6 T[n] = T[n/2] + T[n/4]
② f[n]是关于f[n-1]的递推式,打表打出f[100W],f[200W],...,f[10E]。
求f[123456789] = f[123000000] 再往后推456789项。 O(100W)
【代码实现】
40分代码
#include<bits/stdc++.h> // 29 169
using namespace std;
double ans = 1 ;
long long jishu ;
int main(){
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
int i ;
cin >> i ;
//for(int i = 1 ; i ; i++){
for(int j = 1 ; j <= i ; j++){
ans = ans * 5.82842712474619 ;
jishu = (long long)ans ;
jishu = jishu % 1000000007 ;
if(j%10==0 ) ans = (double)jishu+1 ;
//cout << ans << " !" << endl ;
}
cout << jishu << endl ;
ans = 1 ;
jishu = 1 ;
//}
}
博主闲的没事在考场上打的40分的表(在这里卡了2h)
/*
Coded by Apojacsleam
*/
#include<cstdio>
int n;
int a[11]={1,5,33,197,1153,6725,39201,228485,1331713,7761797,45239073};
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
scanf("%d",&n);
if(n<=10) printf("%d\n",a[n]);
return 0;
}
60分选手的代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int mo=1e9+7;
int k,n,c[5000005],san[10000005],ba[5000005],i,j,ans;
int pow(int x,int y){
int a=x,res=1;
while(y){
if(y&1)res=(long long)res*(long long)a%mo;
a=(long long)a*(long long)a%mo;
y>>=1;
}
return res;
}
int main(){
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
cin>>n;
ba[0]=1;c[0]=1;
for(i=1;i<=n/2;i++){
int res=(long long)c[i-1]*(long long)(n-(i*2-1)+1)%mo*(long long)pow(i*2-1,mo-2)%mo;
c[i]=((long long)res*(long long)(n-i*2+1)%mo)*(long long)pow(i*2,mo-2)%mo;
ba[i]=(long long)ba[i-1]*8%mo;
}
san[0]=1;
for(i=1;i<=n;i++)san[i]=(long long)san[i-1]*(long long)3%mo;
for(k=0;k<=n/2;k++){
ans=((long long)ans+(long long)c[k]*(long long)ba[k]%mo*(long long)san[n-k*2]%mo)%mo;
}
ans=((long long)2*ans%mo-1+mo)%mo;
cout<<ans<<endl;
return 0;
}
80分选手的代码
#include <cstdio>
const int MOD = 1000000007, MAX_N = 1e7;
int n;
int a[2 * MAX_N + 100];
int main() {
freopen("math.in", "r", stdin);
freopen("math.out", "w", stdout);
scanf("%d", &n);
n *= 2;
a[0] = 2; a[1] = 2;
for (int i = 2; i <= n; ++i) a[i] = ((long long)a[i - 1] * 2 + a[i - 2]) % MOD;
// for (int i = 0; i <= n; ++i) printf("%d ", a[i]);
printf("%d", (a[n] - (n & 1 ? 0 : 1) + MOD) % MOD);
return 0;
}
博主在考场上闲的没事写的100分代码
/*
Coded by Apojacsleam
*/
#include<cstdio>
#define mod 1000000007
long long a,b,n;
struct NODE{
int r,c;
long long f[2][2];
};
NODE f1,f2,f3;
NODE cheng(NODE &a,NODE &b)
{
NODE c;
c.r=a.r;
c.c=b.c;
for(register int i=0;i<a.r;i++)
for(register int j=0;j<b.c;j++)
{
c.f[i][j]=0;
for(register int k=0;k<a.c;k++) c.f[i][j]+=a.f[i][k]*b.f[k][j];
c.f[i][j]%=mod;
}
return c;
}
NODE ksm(int n)
{
NODE res=f1,temp=f2;
while(n)
{
if(n&1) res=cheng(res,temp);
temp=cheng(temp,temp);
n>>=1;
}
return res;
}
void doit()
{
f1.r=f1.c=f2.c=f2.r=2;
f1.f[0][0]=1;f1.f[0][1]=0;f1.f[1][0]=0;f1.f[1][1]=1;
f2.f[0][0]=0;f2.f[0][1]=1;f2.f[1][0]=b-a*a;f2.f[1][1]=2*a;
f3.r=2;f3.c=1;f3.f[0][0]=2*a;f3.f[1][0]=2*(a*a+b);
}
long long ans;
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
a=3;b=8;
scanf("%lld",&n);
doit();
if(n==1) ans=(2*a)%mod;
else if(n==2) ans=(2*(a*a+b));
else
{
NODE res=ksm(n-2);
f3=cheng(res,f3);
ans=(f3.f[1][0]+mod)%mod;
}
ans=(ans+mod-1)%mod;
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
return 0;
}