A
学习了一下题解,好像很牛逼啊,这个ll爆得也很灵性,tls牛逼啊。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
ll one=1;
char buf[30000003];
ll rdp=0;
inline ll read(){
ll ret=0;
while(buf[rdp]>='0'&&buf[rdp]<='9'){
ret*=10;
ret+=buf[rdp++]-'0';
}
rdp++;
return ret;
}
struct edge{
ll u,v,w;
}a[200003],b[200003];
bool cmp(edge a,edge b){
return a.w>b.w;
}
ll totb;
struct query{
ll u,v,w;
}que[200003];
ll totq;
struct tedge{
ll to,next,id;
}e[300003];
ll head[100003];
ll cnt;
ll pa[100003];
ll pid[100003];
ll depth[100003];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(ll u,ll v,ll id){
e[cnt].to=v;
e[cnt].next=head[u];
e[cnt].id=id;
head[u]=cnt++;
}
void dfs(ll u,ll fa,ll id){
pa[u]=fa;
pid[u]=id;
depth[u]=depth[fa]+1;
for(ll i=head[u];~i;i=e[i].next){
ll v=e[i].to;
if(v==fa)continue;
dfs(v,u,e[i].id);
}
}
struct Dsu{
ll fa[100003];
ll cnt[100003][31];
ll siz[100003];
void init(ll n){
for(ll i=1;i<=n;i++){
fa[i]=i;
siz[i]=1;
for(ll j=0;j<31;j++){
if((1ll<<j)&i)cnt[i][j]=1;
else cnt[i][j]=0;
}
}
}
ll getfa(ll u){
if(u==fa[u])return u;
return fa[u]=getfa(fa[u]);
}
bool check(ll u,ll v){
u=getfa(u);
v=getfa(v);
if(u==v)return true;
return false;
}
void Union(ll u,ll v){
u=getfa(u);
v=getfa(v);
fa[u]=v;
siz[v]+=siz[u];
for(ll i=0;i<31;i++)cnt[v][i]+=cnt[u][i];
}
ll calc(ll u,ll v,ll w){
ll ret=0;
u=getfa(u);
v=getfa(v);
for(ll i=0;i<31;i++){
if((1<<i)&w){
ret+=one*cnt[u][i]*cnt[v][i]*(1ll<<i);
ret+=one*(siz[u]-cnt[u][i])*(siz[v]-cnt[v][i])*(1ll<<i);
}
else {
ret+=one*(siz[u]-cnt[u][i])*cnt[v][i]*(1ll<<i);
ret+=one*cnt[u][i]*(siz[v]-cnt[v][i])*(1ll<<i);
}
}
return ret;
}
}dsu;
ll T;
ll n,m;
int main(){
fread(buf,1,30000000,stdin);
T=read();
while(T--){
n=read();
m=read();
for(ll i=1;i<=m;i++){
a[i].u=read();
a[i].v=read();
a[i].w=read();
}
sort(a+1,a+1+m,cmp);
dsu.init(n);
init();
totb=0,totq=0;
for(ll i=1;i<=m;i++){
ll u=a[i].u;
ll v=a[i].v;
ll w=a[i].w;
if(dsu.check(u,v)){
que[++totq]=(query){u,v,w};
}
else {
b[++totb]=a[i];
addedge(u,v,totb);
addedge(v,u,totb);
dsu.Union(u,v);
}
}
/*cout<<"B:\n";
for(ll i=1;i<=totb;i++){
cout<<b[i].u<<' '<<b[i].v<<' '<<b[i].w<<endl;
}
cout<<"Q:\n";
for(ll i=1;i<=totq;i++){
cout<<que[i].u<<' '<<que[i].v<<' '<<que[i].w<<endl;
}*/
dfs(1,0,0);
for(ll i=1;i<=totq;i++){
ll u=que[i].u,v=que[i].v,w=que[i].w;
while(u!=v){
if(depth[u]>depth[v]){
b[pid[u]].w+=w;
u=pa[u];
}
else {
b[pid[v]].w+=w;
v=pa[v];
}
}
}
/*cout<<"B:\n";
for(ll i=1;i<=totb;i++){
cout<<b[i].u<<' '<<b[i].v<<' '<<b[i].w<<endl;
}*/
dsu.init(n);
sort(b+1,b+1+totb,cmp);
ll sum=0;
for(ll i=1;i<=totb;i++){
sum+=dsu.calc(b[i].u,b[i].v,b[i].w);
dsu.Union(b[i].u,b[i].v);
}
printf("%llu\n",sum);
}
}
B
爆搜就完事了。
#include<bits/stdc++.h>
using namespace std;
int t,k,w,n;
char s[20],smax[20],smin[20];
int ansmin,ansmax;
int zhuan(char * x){
int ans=0;
for(int i=0; x[i]; i++)
ans=ans*10+x[i]-'0';
return ans;
}
void maxdfs(int x, int k){
if(x==n){
ansmax=max(ansmax,zhuan(smax));
return;
}
maxdfs(x+1,k);
if(k)
for(int i=x+1; i<n; i++){
swap(smax[x],smax[i]);
maxdfs(x+1,k-1);
swap(smax[x],smax[i]);
}
return;
}
void mindfs(int x, int k){
if(x==n){
ansmin=min(ansmin,zhuan(smin));
return;
}
mindfs(x+1,k);
if(k)
for(int i=x+1; i<n; i++){
if(x==0 && smin[i]=='0') continue;
swap(smin[x],smin[i]);
mindfs(x+1,k-1);
swap(smin[x],smin[i]);
}
return;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%s%d",s,&k);
n=strlen(s);
for(int i=0; i<=n; i++){
smin[i]=smax[i]=s[i];
}
ansmax=ansmin=zhuan(s);
maxdfs(0,k);
mindfs(0,k);
printf("%d %d\n",ansmin,ansmax);
}
return 0;
}
E
签到。
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
int m;
double R,x,y,r,d,theta;
double ans;
int t;
double yxdl(double a, double b, double c){
return acos((a*a+b*b-c*c)/(2*a*b));
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%lf",&m,&R);
ans=2.0*pi*R;
for(int i=0; i<m; i++){
scanf("%lf%lf%lf",&x,&y,&r);
d=sqrt(x*x+y*y);
if(R+r<d || d+r<R) continue;
theta=yxdl(R,d,r);
ans-=R*2.0*theta;
theta=yxdl(r,d,R);
ans+=r*2.0*theta;
//cout<<i<<" :"<<ans<<endl;
}
printf("%.10lf\n",ans);
}
}
G
数据随机,加了点灵性剪枝跑了线段树。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
const int maxn=100003;
uint w,x,y,z;
uint gao(){
x^=(x<<11);
x^=(x>>4);
x^=(x<<5);
x^=(x>>14);
w=x^y^z;
x=y;
y=z;
z=w;
return z;
}
int T;
int a[maxn];
struct que{
int l,r,p;
}rec[5000003];
int tot;
int n,m;
int mx[maxn<<2];
int lz[maxn<<2];
void pushup(int u){
mx[u]=max(mx[2*u],mx[2*u+1]);
}
void pushdown(int u){
if(lz[u]==0)return;
lz[2*u]=max(lz[2*u],lz[u]);
mx[2*u]=max(mx[2*u],lz[u]);
lz[2*u+1]=max(lz[2*u+1],lz[u]);
mx[2*u+1]=max(mx[2*u+1],lz[u]);
lz[u]=0;
}
void build(int u,int l,int r){
lz[u]=0;
if(l==r){
mx[u]=0;
return ;
}
int mid=(l+r)/2;
build(2*u,l,mid);
build(2*u+1,mid+1,r);
}
void update(int u,int l,int r,int ql,int qr,int x){
if(ql>r||qr<l)return;
if(ql<=l&&r<=qr){
lz[u]=max(lz[u],x);
mx[u]=max(mx[u],x);
return;
}
pushdown(u);
int mid=(l+r)/2;
update(2*u,l,mid,ql,qr,x);
update(2*u+1,mid+1,r,ql,qr,x);
pushup(u);
}
int query(int u,int l,int r,int pos){
if(pos>r||pos<l)return 0;
if(l==r)return mx[u];
pushdown(u);
int mid=(l+r)/2;
return max(query(2*u,l,mid,pos),query(2*u+1,mid+1,r,pos));
}
int main(){
scanf("%d",&T);
while(T--)
{
tot=0;
scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
for(int i=1;i<=m;i++){
int l=gao()%n+1;
int r=gao()%n+1;
int v=gao()%(1<<30);
//cout<<l<<' '<<r<<' '<<v<<endl;
if(l>r)swap(l,r);
if(m<=10000)rec[++tot]=(que){l,r,v};
else {
int x=2ll*m*l*(n-r+1)/n/n;
//cout<<x<<endl;
if(x<=1000||v>(1ll<<30)*x/1000/(x/1000+1))rec[++tot]=(que){l,r,v};
}
}
build(1,1,n);
long long ans=0;
for(int i=1;i<=tot;i++)update(1,1,n,rec[i].l,rec[i].r,rec[i].p);
for(int i=1;i<=n;i++){
ans^=1ll*i*query(1,1,n,i);
}
printf("%lld\n",ans);
}
}
H
枚举翻转区间的数字范围dp一下。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int t,n,ans,ansl,ansr;
char s[N];
int dp1[N][10],dp2[N][10],dp3[N][10],l[N][10];
void init(){
ans=0;
}
void work(){
for(int j=0; j<=9; j++)
dp1[0][j]=dp2[n+1][j]=0;
for(int i=1; i<=n; i++)
for(int j=0; j<=9; j++){
dp1[i][j]=dp1[i-1][j];
if(s[i]=='0'+j)
dp1[i][j]++;
if(j)
dp1[i][j]=max(dp1[i][j-1],dp1[i][j]);
}
for(int i=n; i>=1; i--)
for(int j=9; j>=0; j--){
dp2[i][j]=dp2[i+1][j];
if(s[i]=='0'+j)
dp2[i][j]++;
if(j<9)
dp2[i][j]=max(dp2[i][j+1],dp2[i][j]);
}
for(int x=0; x<=9; x++){
for(int y=x; y<=9; y++){
for(int j=x; j<=y; j++){
dp3[0][j]=0;
l[0][j]=0;
}
for(int i=1; i<=n; i++){
for(int j=y; j>=x; j--){
dp3[i][j]=dp3[i-1][j];
l[i][j]=l[i-1][j];
if(s[i]=='0'+j && j==y && dp1[i-1][x]+1>dp3[i][j]){
dp3[i][j]=dp1[i-1][x]+1;
l[i][j]=i;
}
if(s[i]=='0'+j && dp3[i-1][j]+1>dp3[i][j]){
dp3[i][j]=dp3[i-1][j]+1;
l[i][j]=l[i-1][j];
}
if(j<y && dp3[i][j+1]>dp3[i][j]){
dp3[i][j]=dp3[i][j+1];
l[i][j]=l[i][j+1];
}
if(s[i]=='0'+j && j==x && dp2[i+1][y]+dp3[i][j]>ans){
ans=dp2[i+1][y]+dp3[i][j];
ansl=l[i][j];
ansr=i;
}
//if(x==2 && y==3)
//cout<<i<<" "<<j<<":"<<dp3[i][j]<<endl;
}
}
}
}
return;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%s",&n,s+1);
init();
work();
printf("%d %d %d\n",ans,ansl,ansr);
}
return 0;
}
J
先后缀数组求出每种子串出现的次数,然后huffman树。huffman树可以用两个队列做到
O(n)
O
(
n
)
。整体
O(n)
O
(
n
)
。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char buf[30000003];
int rdp=0;
inline int read(){
int ret=0;
while(buf[rdp]>='0'&&buf[rdp]<='9'){
ret*=10;
ret+=buf[rdp++]-'0';
}
rdp++;
return ret;
}
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
const int MAXN = 20000000+100;//n*10
int sa[MAXN];
int Rank[MAXN];
int height[MAXN];
int n;
int s[MAXN];
int wa[MAXN],wb[MAXN],wv[MAXN];
int wws[MAXN];
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i=0;i<n;i++) wv[i]=r[a[i]];
for(i=0;i<m;i++) wws[i]=0;
for(i=0;i<n;i++) wws[wv[i]]++;
for(i=1;i<m;i++) wws[i]+=wws[i-1];
for(i=n-1;i>=0;i--) b[--wws[wv[i]]]=a[i];
return;
}
int c0(int *r,int a,int b)
{return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];}
int c12(int k,int *r,int a,int b)
{if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];}
void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
r[n]=r[n+1]=0;
for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
sort(r+2,wa,wb,tbc,m);
sort(r+1,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=0;i<tbc;i++) san[rn[i]]=i;
for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
if(n%3==1) wb[ta++]=n-1;
sort(r,wb,wa,ta,m);
for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for(i=0,j=0,p=0;i<ta && j<tbc;p++)
sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
return;
}
void calheight(int *r, int *sa, int n)
{
int i, j, k = 0;
for (i = 1; i <= n; ++i) Rank[sa[i]] = i;
for (i = 0; i < n; height[Rank[i++]] = k)
for (k ? k-- : 0, j = sa[Rank[i] - 1]; r[i + k] == r[j + k]; ++k);
return;
}
int stk[2000003];
int cnt[2000003];
ll ans[1000003];
int top;
struct node{
ll x,tim;
};
node que1[2000003];
node que2[2000003];
int head1,head2,tail1,tail2;
void add(ll x,ll tim){
que2[++tail2]=(node){x,tim};
}
void tryunion(){
if(head2<tail2&&que2[tail2].x==que2[tail2-1].x){
que2[tail2-1].tim+=que2[tail2].tim;
tail2--;
}
}
ll gao1(){
ll ret=que1[head1].tim/2*2*que1[head1].x;
add(que1[head1].x*2,que1[head1].tim/2);
que1[head1].tim%=2;
if(que1[head1].tim==0)head1++;
tryunion();
return ret;
}
ll gao2(){
ll ret=que2[head2].tim/2*2*que2[head2].x;
add(que2[head2].x*2,que2[head2].tim/2);
que2[head2].tim%=2;
if(que2[head2].tim==0)head2++;
tryunion();
return ret;
}
ll gao11(){
ll ret=que1[head1].x+que1[head1+1].x;
++head1;
que1[head1].tim--;
if(que1[head1].tim==0)head1++;
add(ret,1);
tryunion();
return ret;
}
ll gao22(){
ll ret=que2[head2].x+que2[head2+1].x;
++head2;
que2[head2].tim--;
if(que2[head2].tim==0)head2++;
add(ret,1);
tryunion();
return ret;
}
ll gao12(){
ll ret=que1[head1].x+que2[head2].x;
que1[head1].tim--;
if(que1[head1].tim==0)head1++;
que2[head2].tim--;
if(que2[head2].tim==0)head2++;
add(ret,1);
tryunion();
return ret;
}
void print(){
printf("debug:\nqueue1:\n");
for(int i=head1;i<=tail1;i++)printf("%lld %lld\n",que1[i].x,que1[i].tim);
printf("queue2:\n");
for(int i=head2;i<=tail2;i++)printf("%lld %lld\n",que2[i].x,que2[i].tim);
}
int main()
{
/* n=8;
s[8]=0;
s[0]=s[1]=2;
s[2]=s[3]=s[4]=s[5]=1;
s[6]=s[7]=3;
dc3(s,sa,n+1,200);
calheight(s,sa,n);
for(int i=0;i<=n;i++){
printf("%d ", sa[i]);
}
printf("\n");
for(int i=1;i<=n;i++){
printf("%d ", height[i]);
}
printf("\n");*/
fread(buf,1,30000000,stdin);
int T;
T=read();
while(T--){
n=read();
for(int i=0;i<n;i++){
s[i]=read();
s[i]++;
ans[i+1]=0;
}
s[n]=0;
dc3(s,sa,n+1,200);
calheight(s,sa,n);
top=0;
++top;
stk[top]=0;
cnt[top]=1;
++top;
stk[top]=n-sa[1];
cnt[top]=1;
for(int i=2;i<=n;i++){
int len=n-sa[i];
int cm=height[i];
int tmp=0;
while(top>0&&cm<=stk[top]){
tmp+=cnt[top];
ans[tmp]+=stk[top]-stk[top-1];
top--;
}
if(top>0)ans[tmp]-=(cm-stk[top]);
++top;
stk[top]=cm;
cnt[top]=tmp;
++top;
stk[top]=len;
cnt[top]=1;
}
int tmp=0;
for(int i=top;i>=2;i--){
tmp+=cnt[i];
ans[tmp]+=stk[i]-stk[i-1];
}
head1=head2=1,tail1=tail2=0;
for(int i=1;i<=n;i++){
if(ans[i]!=0)que1[++tail1]=(node){i,ans[i]};
}
ll p=0;
ll q=1ll*n*(n+1)/2;
if(n==1){
printf("0\n");
continue;
}
while(1){
if(head1>tail1&&head2==tail2&&que2[head2].tim==1)break;
if(head2>tail2||(head1<=tail1&&que1[head1].x<que2[head2].x)){
if(que1[head1].tim>=2){
p+=gao1();
}
else {
if(head2>tail2||(head1<tail1&&que1[head1+1].x<que2[head2].x)){
p+=gao11();
}
else {
p+=gao12();
}
}
}
else {
if(que2[head2].tim>=2){
p+=gao2();
}
else {
if(head1>tail1||(head2<tail2&&que2[head2+1].x<que1[head1].x)){
p+=gao22();
}
else {
p+=gao12();
}
}
}
}
ll g=__gcd(p,q);
p/=g,q/=g;
if(q==1)printf("%lld\n",p);
else printf("%lld/%lld\n",p,q);
}
}
K
这玩意的置换群和正12面体差不多,于是burnside一下。限制条件用类似背包的做法搞一下。模数不是素数就用60p做模数,最后除掉60。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll P;
long long mul(long long x,long long y)
{
return (x*y-(long long)(x/(long double)P*y+1e-3)*P+P)%P;
}
int n,p;
int a[70];
ll C[70][70];
ll dp[70][70];
int main(){
//cout<<ans<<endl;
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
P=1ll*p*60;
C[0][0]=1;
C[1][0]=C[1][1]=1;
for(int i=1;i<=60;i++){
for(int j=0;j<=i;j++){
if(j==0||j==i)C[i][j]=1;
else C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
}
}
ll ans=0;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=60;j++){
if(j<a[i])continue;
for(int k=j;k<=60;k++){
dp[i][k]=(dp[i][k]+mul(C[k][j],dp[i-1][k-j]))%P;
}
}
}
ans=(ans+dp[n][60])%P;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=12;j++){
if(5*j<a[i])continue;
for(int k=j;k<=12;k++){
dp[i][k]=(dp[i][k]+mul(C[k][j],dp[i-1][k-j]))%P;
}
}
}
ans=(ans+mul(24,dp[n][12]))%P;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=30;j++){
if(2*j<a[i])continue;
for(int k=j;k<=30;k++){
dp[i][k]=(dp[i][k]+mul(C[k][j],dp[i-1][k-j]))%P;
}
}
}
ans=(ans+mul(15,dp[n][30]))%P;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=20;j++){
if(3*j<a[i])continue;
for(int k=j;k<=20;k++){
dp[i][k]=(dp[i][k]+mul(C[k][j],dp[i-1][k-j]))%P;
}
}
}
ans=(ans+mul(20,dp[n][20]))%P;
ans=ans/60;
printf("%lld\n",ans);
}
}