A
由于小数点之后只有一位,可以随机一下。
#include<bits/stdc++.h>
using namespace std;
const int canshu=10;
int cs;
int t,n;
double x;
struct node{
double x,y;
int num;
}a[10005];
int tot;
bool cmp(node a, node b){
if(a.num!=b.num)
return a.num>b.num;
else if(a.x!=b.x)
return a.x<b.x;
else return a.y<b.y;
}
void quchong(){
tot=n;
sort(a,a+n,cmp);
int j=-1;
for(int i=0; i<n; i++){
if(j==-1 || a[i].x!=a[j].x || a[i].y!=a[j].y){
j=i;
}
else{
a[j].num+=a[i].num;
a[i].num=0;
tot--;
}
}
sort(a,a+n,cmp);
/*
cout<<tot<<endl;
for(int i=0; i<tot; i++){
}
*/
return;
}
inline bool check(node a, node b, node c){
return (b.y-a.y)*(c.x-a.x)==(b.x-a.x)*(c.y-a.y);
}
int main(){
scanf("%d",&t);
srand(time(0));
for(int tt=1; tt<=t; tt++){
scanf("%d%lf",&n,&x);
for(int i=0; i<n; i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
a[i].num=1;
}
quchong();
if(tot==1){
printf("Yes\n");
continue;
}
cs=1.0*canshu/(x*x);
int m;
bool flag=0;
//cout<<"cs:"<<cs<<endl;
for(int k=0; k<cs; k++){
int l=0,r=0;
l=rand()%tot;
r=rand()%tot;
while(r==l)
r=rand()%tot;
m=a[l].num+a[r].num;
for(int i=0; i<tot; i++){
if(i==l || i==r) continue;
if(check(a[l],a[r],a[i]))
m+=a[i].num;
}
//cout<<l<<" "<<r<<" : "<<m<<endl;
if(1.0*m>=x*n){
flag=1;
break;
}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
B
签到。
#include<bits/stdc++.h>
using namespace std;
int t,n;
int tot=0,ans[100005],sum;
int main(){
scanf("%d",&t);
for(int tt=1; tt<=t; tt++){
scanf("%d",&n);
sum=0;
tot=0;
int i;
for(i=1; i*i<n; i++){
if(n%i==0){
ans[tot++]=i;
sum+=i+n/i;
}
}
if(i*i==n) sum+=i;
//cout<<sum<<endl;
if(sum==2*n){
printf("Case %d: %d = 1",tt,n);
for(i=1; i<tot; i++)
printf(" + %d",ans[i]);
for(int i=tot-1; i>0; i--)
printf(" + %d",n/ans[i]);
printf("\n");
}
else{
printf("Case %d: Not perfect.\n",tt);
}
}
return 0;
}
C
先判断两个线段的公垂线是否与线段相交,是的话就是交点之间的距离,否则就是每个端点到另一条线段的距离。
#include<bits/stdc++.h>
using namespace std;
//#define eps 1e-8
//#define zero(x) (((x)>0?(x):-(x))<eps)
#define distance dis
#define ll long long
const ll inf=1e9;
struct point3{ll x,y,z;};
struct line3{point3 a,b;};
struct plane3{point3 a,b,c;};
struct myfloat{
ll p,q;
};
bool operator < (const myfloat a, const myfloat b){
return a.p*b.q<b.p*a.q;
}
//计算 cross product U x V
point3 xmult(point3 u,point3 v){
point3 ret;
ret.x=u.y*v.z-v.y*u.z;
ret.y=u.z*v.x-u.x*v.z;
ret.z=u.x*v.y-u.y*v.x;
return ret;
}
//计算 dot product U . V
ll dmult(point3 u,point3 v){
return u.x*v.x+u.y*v.y+u.z*v.z;
}
//矢量差 U - V
point3 subt(point3 u,point3 v){
point3 ret;
ret.x=u.x-v.x;
ret.y=u.y-v.y;
ret.z=u.z-v.z;
return ret;
}
//两点距离,单参数取向量大小
ll distance(point3 p1,point3 p2){
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z);
}
//向量大小
ll vlen(point3 p){
return p.x*p.x+p.y*p.y+p.z*p.z;
}
myfloat ptoline(point3 p,line3 l){
return (myfloat){vlen(xmult(subt(p,l.a),subt(l.b,l.a))) , distance(l.a,l.b)};
}
myfloat linetoline(line3 u,line3 v){
point3 n=xmult(subt(u.a,u.b),subt(v.a,v.b));
return (myfloat){dmult(subt(u.a,v.a),n)*dmult(subt(u.a,v.a),n),vlen(n)};
}
/*
int parallel(line3 u,line3 v){
return vlen(xmult(subt(u.a,u.b),subt(v.a,v.b)))==0;
}
*/
void input(ll &x){
scanf("%lld",&x);
}
void output(myfloat x){
ll s[35];
for(int i=0; i<=32; i++){
s[i]=x.p/x.q;
x.p%=x.q;
x.p*=10;
}
s[31]+=5;
for(int i=31; i>0; i--){
if(s[i]>9){
s[i]-=10;
s[i-1]++;
}
else
break;
}
printf("%lld.",s[0]);
for(int i=1; i<=30; i++){
printf("%lld",s[i]);
}
printf("\n");
return;
}
int getd(point3 x, line3 u){
if(dmult(subt(x,u.a),subt(u.b,u.a))<0)
return -1;
if(dmult(subt(x,u.b),subt(u.a,u.b))<0)
return 1;
return 0;
}
myfloat ptoseg(point3 x, line3 u){
if(u.a.x==u.b.x && u.a.y==u.b.y && u.a.z==u.b.z)
return (myfloat){dis(x,u.a),1};
if(getd(x,u)>0)
return (myfloat){dis(x,u.b),1};
if(getd(x,u)<0)
return (myfloat){dis(x,u.a),1};
return ptoline(x,u);
}
int t;
int main(){
scanf("%d",&t);
for(int tt=1; tt<=t; tt++){
line3 a,b;
input(a.a.x);
input(a.a.y);
input(a.a.z);
input(a.b.x);
input(a.b.y);
input(a.b.z);
input(b.a.x);
input(b.a.y);
input(b.a.z);
input(b.b.x);
input(b.b.y);
input(b.b.z);
myfloat ans=(myfloat){inf,1};
point3 n=xmult(subt(a.a,a.b),subt(b.a,b.b));
point3 p1=xmult(subt(a.b,a.a),n),p2=xmult(subt(b.b,b.a),n);
if(dmult(subt(b.a,a.a),p1)*dmult(subt(b.b,a.a),p1)<0 && (dmult(subt(a.a,b.a),p2)*dmult(subt(a.b,b.a),p2))<0){
if(vlen(n)!=0)
ans=linetoline(a,b);
else ans=(myfloat){0,1};
//cout<<ans.p<<" "<<ans.q<<endl;
//output(ans);
}
ans=min(ans,ptoseg(a.a,b));
ans=min(ans,ptoseg(a.b,b));
ans=min(ans,ptoseg(b.a,a));
ans=min(ans,ptoseg(b.b,a));
output(ans);
}
return 0;
}
D
正弦定理xjb迭代下。
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
int t,n;
double l,s,xs,theta,delta;
inline double getarea(double l){
return 0.5*n*sin(theta)*(l/2.0/sin(theta/2.0))*(l/2.0/sin(theta/2.0));
}
int main(){
scanf("%d",&t);
for(int tt=1; tt<=t; tt++){
scanf("%d%lf%lf",&n,&l,&s);
theta=2.0*pi/n;
delta=pi-theta;
xs=sin(delta)/(2.0*sin(theta/2.0));
double tmpl=l;
int ans=0;
while(getarea(tmpl)>s){
tmpl*=xs;
ans++;
}
printf("%d\n",ans);
}
return 0;
}
E
倍长字符串,发现最终的回文串在倍长的字符串上是连续的一段。问题就变成了求修改两个以内字符的最长回文子串。先hash一下,枚举中心,做一次二分,把边界上坏的改了,继续二分,再把边界上坏的改了,再二分下,就完了。时限比较紧,要自然溢出。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
int T;
char s[200003];
ll pw[200003];
ll h1[200003];
ll h2[200003];
ll gethash1(int l,int r){
return h1[r]-h1[l-1]*pw[r-l+1];
}
ll gethash2(int l,int r){
return h2[l]-h2[r+1]*pw[r-l+1];
}
int main(){
scanf("%d",&T);
pw[0]=1;
for(int i=1;i<=200000;i++)pw[i]=pw[i-1]*131;
while(T--){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++)s[i+n]=s[i];
h1[0]=0;
for(int i=1;i<=2*n;i++)h1[i]=s[i]-'a'+1+h1[i-1]*131;
h2[2*n+1]=0;
for(int i=2*n;i>=1;i--)h2[i]=s[i]-'a'+1+h2[i+1]*131;
int ans=1;
for(int i=1;i<=2*n;i++){
int l=1,r=min(i,2*n-i+1),tag=-1;
while(1){
if(r-l<=1){
if(gethash1(i-r+1,i)==gethash2(i,i+r-1))tag=r;
else tag=l;
break;
}
int mid=(l+r)/2;
if(gethash1(i-mid+1,i)==gethash2(i,i+mid-1))l=mid;
else r=mid;
}
int bd=tag+2;
l=bd-1,r=min(i,2*n-i+1);
if(l>r){
ans=max(ans,2*r-1);
continue;
}
while(1){
if(r-l<=1){
if(gethash1(i-r+1,i-bd+1)==gethash2(i+bd-1,i+r-1))tag=r;
else tag=l;
break;
}
int mid=(l+r)/2;
if(gethash1(i-mid+1,i-bd+1)==gethash2(i+bd-1,i+mid-1))l=mid;
else r=mid;
}
bd=tag+2;
l=bd-1,r=min(i,2*n-i+1);
if(l>r){
ans=max(ans,2*r-1);
continue;
}
while(1){
if(r-l<=1){
if(gethash1(i-r+1,i-bd+1)==gethash2(i+bd-1,i+r-1))tag=r;
else tag=l;
break;
}
int mid=(l+r)/2;
if(gethash1(i-mid+1,i-bd+1)==gethash2(i+bd-1,i+mid-1))l=mid;
else r=mid;
}
ans=max(ans,2*tag-1);
}
if(ans>n)ans=n;
if(ans%2==0)ans--;
printf("%d\n",ans);
}
}
F
枚举x的坐标,每个圆覆盖一段区间,区间求并。
#include <bits/stdc++.h>
using namespace std;
const int N=20001;
const int Q=201;
int n,m,q,T,x,y,r;
struct seg{
int l,r;
};
bool operator<(const seg& a,const seg& b){
if(a.l!=b.l)
return a.l<b.l;
return a.r<b.r;
}
vector<seg>g[N];
int main(){
scanf("%d",&T);
for(int tt=1;tt<=T;tt++){
scanf("%d%d%d",&n,&m,&q);
for(int i=0; i<n; i++){
g[i].clear();
}
for(int j=1; j<=q; j++){
scanf("%d%d%d",&x,&y,&r);
int u,d,len;
for(int i=max(0,x-r); i<=min(n-1,x+r); i++){
len=sqrt(r*r-(x-i)*(x-i));
d=max(y-len,0);
u=min(y+len,m-1);
//cout<<i<<" "<<d<<" "<<u<<endl;
g[i].push_back((seg){d,u});
}
}
int ans=0;
for(int i=0; i<n; i++){
int siz=g[i].size();
sort(g[i].begin(),g[i].end());
int r=-1;
for(int j=0; j<siz; j++){
if(g[i][j].r<=r) continue;
if(g[i][j].l>r){
ans+=g[i][j].r-g[i][j].l+1;
}
else{
ans+=g[i][j].r-r;
}
r=g[i][j].r;
}
}
printf("%d\n",n*m-ans);
}
}
H
打表发现所有的数要么是在环上,要么是在去环的路上,所有的环都是6的因子。不在环上的暴力更新,在环上的用lazy标记处理。
#include <bits/stdc++.h>
using namespace std;
const int maxn=50003;
int a[2018];
bool vis[2018];
int temp[6];
int v[maxn];
int rd[maxn<<2];
int sum[maxn<<2];
int sumr[maxn<<2][6];
int n;
inline void pushup(int u){
sum[u]=sum[2*u]+sum[2*u+1];
if(rd[2*u]==-1||rd[2*u+1]==-1){
rd[u]=-1;
return;
}
rd[u]=0;
for(int i=0;i<6;i++)sumr[u][i]=0;
for(int i=0;i<6;i++)sumr[u][i]+=sumr[2*u][(rd[2*u]+i)%6];
for(int i=0;i<6;i++)sumr[u][i]+=sumr[2*u+1][(rd[2*u+1]+i)%6];
}
inline void pushdown(int u){
if(rd[u]<=0)return;
rd[2*u]=(rd[2*u]+rd[u])%6;
sum[2*u]=sumr[2*u][rd[2*u]];
rd[2*u+1]=(rd[2*u+1]+rd[u])%6;
sum[2*u+1]=sumr[2*u+1][rd[2*u+1]];
for(int i=0;i<6;i++)temp[i]=sumr[u][(rd[u]+i)%6];
for(int i=0;i<6;i++)sumr[u][i]=temp[i];
rd[u]=0;
}
void build(int u,int l,int r){
if(l==r){
sum[u]=v[l];
if(vis[sum[u]]){
rd[u]=0;
sumr[u][0]=sum[u];
for(int i=1;i<6;i++){
sumr[u][i]=sumr[u][i-1]*sumr[u][i-1]%2018;
}
}
else {
rd[u]=-1;
}
return;
}
int mid=(l+r)/2;
build(2*u,l,mid);
build(2*u+1,mid+1,r);
pushup(u);
}
void update(int u,int l,int r,int ql,int qr){
if(ql>r||qr<l)return;
if(ql<=l&&r<=qr&&rd[u]!=-1){
rd[u]=(rd[u]+1)%6;
sum[u]=sumr[u][rd[u]];
return;
}
if(l==r){
sum[u]=sum[u]*sum[u]%2018;
if(vis[sum[u]]){
rd[u]=0;
sumr[u][0]=sum[u];
for(int i=1;i<6;i++){
sumr[u][i]=sumr[u][i-1]*sumr[u][i-1]%2018;
}
}
else {
rd[u]=-1;
}
return ;
}
int mid=(l+r)/2;
pushdown(u);
update(2*u,l,mid,ql,qr);
update(2*u+1,mid+1,r,ql,qr);
pushup(u);
}
int query(int u,int l,int r,int ql,int qr){
if(ql>r||qr<l)return 0;
if(ql<=l&&r<=qr)return sum[u];
int mid=(l+r)/2;
pushdown(u);
int ret=0;
ret+=query(2*u,l,mid,ql,qr);
ret+=query(2*u+1,mid+1,r,ql,qr);
return ret;
}
int main(){
int cnt=0;
for(int i=0;i<2018;i++){
memset(a,-1,sizeof(a));
int tmp=i;
for(int j=0;;j++){
if(a[tmp]==-1)a[tmp]=j;
else {
if(tmp==i)vis[i]=true;
else cnt;
break;
}
tmp=tmp*tmp%2018;
}
}
/*for(int i=0;i<2018;i++)if(vis[i]){
int p=i;
for(int j=1;j<=6;j++){
p=p*p%2018;
}
if(p!=i)cout<<"sb\n";
}*/
int T;
scanf("%d",&T);
for(int tt=1;tt<=T;tt++){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
build(1,1,n);
printf("Case #%d:\n",tt);
int q;
scanf("%d",&q);
while(q--){
char op[3];
int l,r;
scanf("%s%d%d",op,&l,&r);
if(op[0]=='C')update(1,1,n,l,r);
else printf("%d\n",query(1,1,n,l,r));
}
}
}
J
枚举SOD,数位dp一下。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[14][109][109][109];
int dig[14];
int add[14][109];
ll n;
int tot;
ll dfs(int pos,int mod,int sum,int status,int limit){
if(pos<1){
if(sum==mod&&status==0)return 1;
else return 0;
}
if(sum>mod)return 0;
if(!limit&&dp[pos][mod][sum][status]!=-1){
return dp[pos][mod][sum][status];
}
int end=limit?dig[pos]:9;
ll ret=0;
for(int i=0;i<=end;i++){
ret+=dfs(pos-1,mod,sum+i,(status+add[pos][mod]*i)%mod,limit&&(i==end));
}
if(!limit)dp[pos][mod][sum][status]=ret;
return ret;
}
int main(){
int T;
scanf("%d",&T);
memset(dp,-1,sizeof(dp));
for(int i=1;i<=108;i++){
int tmp=1;
for(int j=1;j<=13;j++){
add[j][i]=tmp;
tmp=tmp*10%i;
}
}
for(int tt=1;tt<=T;tt++){
scanf("%lld",&n);
ll ans=0;
if(n==1000000000000ll){
n--;
ans++;
}
tot=0;
while(n){
dig[++tot]=n%10;
n/=10;
}
for(int i=1;i<=tot*9;i++)ans+=dfs(tot,i,0,0,1);
printf("Case %d: %lld\n",tt,ans);
}
}
K
签到。
#include<bits/stdc++.h>
using namespace std;
const int N=30;
int t;
int a[N][N],b[N][N],c[N][N];
int m,n,p,q;
int main(){
scanf("%d",&t);
for(int tt=1; tt<=t; tt++){
memset(c,0,sizeof(c));
scanf("%d%d%d%d",&n,&m,&p,&q);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
scanf("%d",&a[i][j]);
for(int i=0; i<p; i++)
for(int j=0; j<q; j++)
scanf("%d",&b[i][j]);
if(m!=p){
printf("Case %d:\nERROR\n",tt);
}
else{
for(int i=0; i<n; i++){
for(int j=0; j<q; j++){
for(int k=0; k<m; k++)
c[i][j]+=a[i][k]*b[k][j];
}
}
printf("Case %d:\n",tt);
for(int i=0; i<n; i++){
for(int j=0; j<q; j++)
printf("%d%c",c[i][j],j==q-1?'\n':' ');
}
}
}
}