noip模拟32
A.Smooth
这道题单是水过去的方法就很多..
最初还幻想着本地把所有数据跑出来然后\(O(1)\)出结果..但是直接把电脑卡死..
正解是使用队列,每次取出\(B\)个队列的队首,比较对首的大小,然后把最小的压进去就可以..
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigend ll
#define re register ll
#define lf double
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memset(x,y,sizeof x)
inline ll read() {
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll N=20;
ll n,m,s,cnt;
ll x[N],k[(int)1e7+50],pri[N];
queue<ll> f[N];
signed main(){
s=read(); n=read();
pri[1]=2; pri[2]=3; pri[3]=5;
pri[4]=7; pri[5]=11; pri[6]=13;
pri[7]=17; pri[8]=19; pri[9]=23;
pri[10]=29; pri[11]=31; pri[12]=37;
pri[13]=41; pri[14]=43; pri[15]=47;
for(re i=1;i<=s;i++){
f[i].push(pri[i]);
}
ll pos,minn,temp;
while(true){
minn=1e18;
for(re j=1;j<=s;j++){
x[j]=f[j].front();
if(x[j]<minn) minn=x[j],pos=j;
}
temp=f[pos].front(); f[pos].pop();
if(k[cnt]==temp) continue;
k[++cnt]=temp; if(cnt>=n) break;
for(re j=pos;j<=s;j++){
f[j].push(temp*pri[j]);
}
}
printf("%lld",k[n-1]);
return 0;
}
B.Six
一道很明显的状压..最初想着要写一个\(O(2^{12}*6^2)\)的Dp,后来发现根本做不到..
于是开始想着\(O(2^{24}*6)\)..
八进制压位,记录自己是和哪位数字\(x\)一起进入的状态..
注意记录自己和\(x\)一起进来的时候,要保证这个\(x\)曾经没有出现过,要不然会出现可以转移的状态转移不进来的情况..
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigend ll
#define re register ll
#define lf double
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memset(x,y,sizeof x)
inline ll read() {
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll mod=1e9+7;
ll m,n,cnt,tot,ans;
ll pri[10],num[10];
ll t[1<<20],dp[1<<20],fst;
inline void Div(){
ll s=sqrt(n),now=n;
for(re i=2;i<=s;i++){
if(now%i==0){
pri[++cnt]=i;
while(now%i==0) now/=i,num[cnt]++;
}
}
if(now>1) pri[++cnt]=now,num[cnt]=1;
return ;
}
signed main(){
n=read(); ll s=sqrt(n);
Div();
fill(t+1,t+(1<<cnt),1); //~~~
for(re i=0;i<=(1<<cnt)-1;i++){
for(re j=cnt;j>=1;j--){
if((i>>(j-1))&1) t[i]=(t[i]*num[j])%mod;
}
}
ll temp,flag,now;
dp[0]=1;
for(re i=0;i<=(1<<(cnt*3))-1;i++){
for(re j=0;j<=(1<<cnt)-1;j++){
flag=0; now=0;
for(re k=1;k<=cnt;k++){
if((j>>(k-1))&1){
temp=(i>>(k*3-3))&7;
if(!temp) continue;
if(temp==7) { flag++; break; }
if(now and (!(now&(1<<(temp-1))))) { flag++; break; }
now|=(1<<(temp-1));
}
}
if(flag) continue; temp=i;
fst=0;
for(re k=1;k<=cnt;k++){
if(((j>>(k-1))&1) and (!((i>>(3*k-3))&7))){
fst=k; break;
}
}
for(re k=1;k<=cnt;k++){
if((j>>(k-1))&1){
if((temp>>(k*3-3))&7) temp|=7<<(3*k-3);
else temp|=fst<<(3*k-3);
}
}
dp[temp]=(dp[temp]+(dp[i]*t[j])%mod)%mod;
}
ans=(ans+dp[i])%mod;
}
printf("%lld",ans-dp[0]);
return 0;
}
C.Walker
考场上一开始想着推一推向量,发现不可行..
于是想着要消元..但是始终不能得到正确的解题思路..
这个题将未知数拆解为\(4\)个,然后使用两组数据,从而构造四个方程组,并用概率得到答案..
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigend ll
#define re register ll
#define lf double
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memset(x,y,sizeof x)
inline ll read() {
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll N=1e5+50;
const lf eps=1e-6;
ll m,n,flag;
lf a[1000][1000],w[1000],ans[1000];
struct I { lf x,y,x2,y2; } p[N];
inline void Guass(){
ll pos; lf temp;
for(re i=1;i<=4;i++){
/* for(re j=1;j<=4;j++){
for(re k=1;k<=5;k++){
printf("%.2lf ",a[j][k]);
}
puts("");
}
puts("");
*/ pos=0;
for(re j=i;j<=5;j++){ // 枚举列
for(re k=i;k<=4;k++){
if(a[k][j]+eps>0 and a[k][j]-eps<0) continue;
if(k!=i){
for(re h=1;h<=5;h++){
swap(a[i][h],a[k][h]);
}
}
pos=j; break;
}
if(pos) break;
}
if((!pos) or (a[i][pos]<eps and a[i][pos]>-eps)) continue;
for(re j=i+1;j<=4;j++){
if(a[j][pos]+eps>0 and a[j][pos]-eps<0) continue;
temp=a[j][pos]/a[i][pos];
for(re k=pos;k<=5;k++){
a[j][k]-=temp*a[i][k];
}
}
}
for(re i=4;i>=1;i--){
temp=a[i][5];
for(re j=i+1;j<=4;j++){
temp-=a[i][j]*w[j];
}
w[i]=temp/a[i][i];
}
// printf("%0.2lf %.2lf %.2lf %.2lf\n",w[1],w[2],w[3],w[4]);
// puts("");
return ;
}
inline void Check(){
ll res=0;
for(re i=1;i<=n;i++){
// printf("%.3lf %.3lf\n",p[i].x*w[1]-p[i].y*w[2]+w[3],p[i].x*w[2]+p[i].y*w[1]+w[4]);
// printf("%.3lf %.3lf\n",p[i].x2,p[i].y2); puts("");
if(p[i].x*w[1]-p[i].y*w[2]+w[3]+eps>p[i].x2)
if(p[i].x*w[1]-p[i].y*w[2]+w[3]-eps<p[i].x2)
if(p[i].x*w[2]+p[i].y*w[1]+w[4]+eps>=p[i].y2)
if(p[i].x*w[2]+p[i].y*w[1]+w[4]-eps<=p[i].y2)
res++;
}
if(res>=((n+1)>>1)){
flag=1; lf temp;
ans[1]=atan((lf)(w[2]*1.0/w[1]));
ans[2]=w[1]*1.0/cos(ans[1]);
if(ans[2]<=0) ans[2]=w[2]*1.0/sin(ans[1]);
if(ans[2]<=0) ans[2]=-ans[2];
ans[1]=acos(w[1]*1.0/ans[2]);
if(w[2]<0) ans[1]*=-1;
ans[3]=w[3],ans[4]=w[4];
}
return ;
}
signed main(){
// File(0.in,out);
srand(time(0));
ll t1=clock();
n=read();
for(re i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].x2,&p[i].y2);
}
while(clock()-t1<=900000)
{
ll i=rand()%n+1,j=rand()%n+1;
if(i==j) continue;
a[1][1]=p[i].x,a[1][2]=-p[i].y;
a[1][3]=1,a[1][4]=0,a[1][5]=p[i].x2;
a[2][1]=p[i].y,a[2][2]=p[i].x;
a[2][3]=0,a[2][4]=1,a[2][5]=p[i].y2;
a[3][1]=p[j].x,a[3][2]=-p[j].y;
a[3][3]=1,a[3][4]=0,a[3][5]=p[j].x2;
a[4][1]=p[j].y,a[4][2]=p[j].x;
a[4][3]=0,a[4][4]=1,a[4][5]=p[j].y2;
/* cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].x2<<" "<<p[i].y2<<'\n';
cout<<p[j].x<<" "<<p[j].y<<" "<<p[j].x2<<" "<<p[j].y2<<'\n';
cout<<endl;
*/ Guass(); Check();
if(flag) break;
}
printf("%.10lf\n%.10lf\n%.10lf %.10lf",ans[1],ans[2],ans[3],ans[4]);
return 0;
}