solved 3
rank 2
A(博弈)
题意:平面上有形成正n边形的n个点,两个人轮流行动,每次可以连接两个点,但不能和之前的线相交,当连成凸多边形时获胜,问先手胜还是后手胜。
(待填)
B
题意:有一棵奇形怪状的树(不好描述。。),求两个顶点路径的点权和。
找找规律乱搞。。
#include <bits/stdc++.h> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/hash_policy.hpp> #include<ext/pb_ds/priority_queue.hpp> using namespace std; using namespace __gnu_pbds; #define rep(i,n) for(int i=1;i<=n;i++) #define ll long long #define pb push_back #define mp make_pair #define st first #define nd second const int N =1e5 + 7 ; ll get(ll x){ ll res=1; while((res-1)*2<x){ res=res*2; } return res-1; } vector<ll> patha,pathb; int main() { ll a,b,ans=0; cin>>a>>b; ll fa=get(a),fb=get(b); ll aa=fa,bb=fb; ll po=(fa+1)/2; while(fa!=a){ patha.pb(fa); if(a>fa)fa=fa+po; else fa=fa-po; po/=2; } patha.pb(a); po=(fb+1)/2; while(fb!=b){ pathb.pb(fb); if(b>fb)fb=fb+po; else fb=fb-po; po/=2; } pathb.pb(b); ll f=-1; int i; for(i=0;i<min(patha.size(),pathb.size());i++){ if(patha[i]==pathb[i]){ f=patha[i]; continue; } ans+=patha[i]+pathb[i]; } if(patha.size()>pathb.size())for(;i<patha.size();i++)ans+=patha[i]; else for(;i<pathb.size();i++)ans+=pathb[i]; if(f!=-1)ans+=f; if(aa>bb)swap(aa,bb); while((aa+1)*2<(bb+1)){ ans+=(aa+1)*2-1; aa=(aa+1)*2-1; } cout<<ans; //for(int i=0;i<patha.size();i++)cout<<patha[i]<<endl; }
01:51(1A)
C
题意:给出每个面含有的顶点个数,每个顶点所在的面的个数,问是否有这样的正多边形,如果有,输出边数、顶点数和面数。
只有4、6、8、12、20五种正多面体,手玩一下打表。
#include <bits/stdc++.h> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/hash_policy.hpp> #include<ext/pb_ds/priority_queue.hpp> using namespace std; using namespace __gnu_pbds; #define rep(i,n) for(int i=1;i<=n;i++) #define ll long long #define pb push_back #define mp make_pair #define st first #define nd second #define gg cout<<-1<<" "<<-1<<" "<<-1<<endl const int N =2e6 + 7 ; int main() { int p,q; while(cin>>p>>q){ if(!p&&!q)break; else if(p==3){ if(q==3)cout<<4<<" "<<6<<" "<<4<<endl; else if(q==4)cout<<6<<" "<<12<<" "<<8<<endl; else if(q==5)cout<<12<<" "<<30<<" "<<20<<endl; else gg; continue; } else if(p==4){ if(q==3)cout<<8<<" "<<12<<" "<<6<<endl; else gg; continue; } else if(p==5){ if(q==3)cout<<20<<" "<<30<<" "<<12<<endl; else gg; continue; } else gg; } }
02:30(1A)
D
题意:一个-1e100到+1e100的坐标轴,有三种移动方式,每种移动方式p(-1e6<p<1e6)代表可以从x走到x+p,可以走无限步,求能到达的点占所有点的比例。
(待填)
E(欧拉函数)
题意:求L-R的欧拉函数和,L<=R<=4e12,R-L<=1e6
先用线性筛筛出2e6之内的素数,然后用这些素数筛这个区间,利用欧拉函数计算公式即可,筛剩下的数一定是素数。
#include <bits/stdc++.h> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/hash_policy.hpp> #include<ext/pb_ds/priority_queue.hpp> using namespace std; using namespace __gnu_pbds; #define rep(i,n) for(int i=1;i<=n;i++) #define ll long long #define pb push_back #define mp make_pair #define st first #define nd second const int N =1e7 + 7 ; int prime[N],notprime[N],cnt; ll a,b; ll re[N],ans[N]; void euler(int n){ notprime[1]=1; for(int i=2;i<=n;i++){ if(!notprime[i]){ prime[++cnt]=i; } for(int j=1;j<=cnt&&prime[j]*i<=n;j++){ notprime[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } } void euler2(ll l,ll r){ for(int i=1;i<=cnt;i++){ for(ll j=l/prime[i]+(l%prime[i]>0);j*prime[i]<=r;j++){ int f=0; while(re[j*prime[i]-l]%prime[i]==0){ re[j*prime[i]-l]/=prime[i]; ans[j*prime[i]-l]*=prime[i]; f=1; } if(f)ans[j*prime[i]-l]=ans[j*prime[i]-l]/prime[i]*(prime[i]-1); } } } int main() { euler(1e7); cin>>a>>b; for(int i=0;i<=b-a;i++)re[i]=i+a,ans[i]=1; euler2(a,b); ll x=0; for(int i=0;i<=b-a;i++){ if(re[i]!=1)ans[i]*=re[i]-1; x+=ans[i]; } cout<<x; }
F
题意:给出一个大于6的这个正整数,把他分解为6个素数的和,保证有解。
小的话就爆搜一下,大的话,偶数分出2 2 2 2,奇数分出2 2 2 3,然后由哥德巴赫猜想,剩下的数一定可以表示成两个素数的和,筛一下素数暴力枚举一下,要更快可以用MR素性测试。
(卡常。。。把枚举顺序反过来才卡过去)
#include <bits/stdc++.h> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/hash_policy.hpp> #include<ext/pb_ds/priority_queue.hpp> using namespace std; using namespace __gnu_pbds; #define rep(i,n) for(int i=1;i<=n;i++) #define ll long long #define pb push_back #define mp make_pair #define st first #define nd second const int N =1e7 + 7 ; struct node{ int st,nd; bool operator < (const node &x)const { if(this->st!=x.st)return this->st<x.st; return this->nd<x.nd; } }; __gnu_pbds::priority_queue<node,less<node>,pairing_heap_tag> q; tree<node,null_type,less<node>,rb_tree_tag,tree_order_statistics_node_update> tr; ll phi[N],prime[N],sum[N]; int isprime[N],cnt; void euler(int n){ phi[1]=1; for(int i=2;i<=n;i++){ if(isprime[i]==0){ prime[++cnt]=i; phi[i]=i-1; } for(int j=1;j<=cnt&&prime[j]*i<=n;j++){ isprime[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } for(int i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i]; } gp_hash_table<ll,int> h; int a[]={2,3,5,7,11,13,17,19}; int f=0; int ans[10]; void dfs(int x,int y){ if(f)return ; if(x<0)return; if(y==7){ if(x==0){rep(i,6)cout<<ans[i]<<" ";f=1;return;} return ; } for(int i=0;i<8;i++)ans[y]=a[i],dfs(x-a[i],y+1); } /*ll cal(ll n){ if(n<N)return sum[n]; if(h[n])return h[n]; ll l=2,r,ans=0; while(l<=n){ r=n/(n/l); ans+=(r-l+1)*cal(n/l); l=r+1; } ans=n*(n+1)/2-ans; return h[n]=ans; }*/ int check(ll x){ if(h[x])return h[x]; ll y=sqrt(x)+1; for(int i=2;i<=y;i++)if(x%i==0)return h[x]=-1; return h[x]=1; } int main() { ll n; euler(1e7); int t; cin>>t; while(t--){ f=0; cin>>n; if(n<=20)dfs(n,1); else { if(n%2==1){ cout<<2<<" "<<2<<" "<<2<<" "<<3<<" "; n-=9; } else { cout<<2<<" "<<2<<" "<<2<<" "<<2<<" "; n-=8; } int now=lower_bound(prime+1,prime+1+cnt,n)-prime-1; for(int i=now;i>=1;i--){ if(check(n-prime[i])>0){ cout<<prime[i]<<" "<<n-prime[i]; break; } } } cout<<endl; } }