5.30 考试修改+总结

悲桑辣么大,总算可以AK一天啦,结果被卡了个unsigned long long QAQ

第一题,我在cojs上放的 简单的求和问题 原题

题解在blog里,我做的数据每个元素不超过10^5

这里不超过10^9,两次求和之后是10^19,刚好爆了long long

所以要用unsigned long long 然后就这样被坑掉了20分

第二题,SDOI 2013 方程原题

题解也在blog里QAQ

容斥一下做组合数取模,写写模板就A了

第三题,thusc的两道题的结合版?

首先题目显然是个FWT的式子,然后做一发FWT之后问题转化成求每个点的A+A^2+A^4+……的值

然后模数很小,不难想到去年thusc的第二题也是平方,也是模数很小

做法是暴力出每个循环节用线段树维护

然后这个题我们先暴力出所有的循环节之后发现求和的时候在环上分成了若干段,每段的和在模意义下都是相等的

这个模数的循环节也特别的有意思,因为除了0和1之外他只有一个大环QAQ

而且每个点最多走一步就会进入环内

我们拆环之后处理一下前缀和,模拟一下跑环可以在O(1)的时间内算出每个点的和

之后FWT还原即可

UPD:std的做法是将i到i^2%mod连边,我们考虑设f(i,j)表示从i这个点出发向后走2^j步的和

然后倍增一下就可以了,之后统计A+A^2+A^4+……就可以直接利用倍增数组统计了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int maxn=300010;
const int mod=10007;
int n,m,u,v,inv=5004;
bool vis[maxn];
int pos[maxn],sum[maxn],tot;
int a[maxn],L[maxn],check[maxn];
int ans[maxn];
bool C[maxn];
int A[maxn],B[maxn];
 
void read(int &num){
    num=0;char ch=getchar();
    while(ch<'!')ch=getchar();
    while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void DFS(int u){
    vis[u]=true;pos[u]=++tot;
    sum[tot]=sum[tot-1]+u;
    if(sum[tot]>=mod)sum[tot]-=mod;
    int v=u*u%mod;
    if(!vis[v])DFS(v);
}
void Get_DP(int u){
    vis[u]=true;
    int v=u*u%mod;
    if(!vis[v])Get_DP(v);
    check[u]=check[v];
    L[u]=L[v]+1;a[u]=a[v]+u;
    if(a[u]>=mod)a[u]-=mod;
}
void FWT(int *A,int n,int flag){
    for(int k=2;k<=n;k<<=1){
        int mk=(k>>1);
        for(int i=0;i<n;i+=k){
            for(int j=0;j<mk;++j){
                int x=A[i+j],y=A[i+j+mk];
                A[i+j]=(x+y)*flag%mod;
                A[i+j+mk]=(x-y+mod)*flag%mod;
            }
        }
    }return;
}
int pow_mod(int v,int p){
    int tmp=1;
    while(p){
        if(p&1)tmp=tmp*v%mod;
        v=v*v%mod;p>>=1;
    }return tmp;
}
 
int main(){
    vis[0]=true;vis[1]=true;DFS(2);
    check[1]=1;
    for(int i=2;i<mod;++i)if(vis[i])check[i]=i;
    for(int i=2;i<mod;++i){
        if(!vis[i])Get_DP(i);
    }
    read(n);read(u);read(v);u++;m=(1<<n);
    for(int i=0;i<m;++i)read(A[i]);
    FWT(A,m,1);
    for(int i=0;i<m;++i){
        int now=A[i],c=u;
        if(C[now]){B[i]=ans[now];continue;}
        if(u<=L[now]){
            for(int j=1;j<=u;++j){
                B[i]=B[i]+A[i];
                if(B[i]>=mod)B[i]-=mod;
                A[i]=A[i]*A[i]%mod;
            }
        }else{
            B[i]=B[i]+a[now];
            if(B[i]>=mod)B[i]-=mod;
            c-=L[now];
            int tmp=check[now];
            if(tmp>1){
                int P=c/tot;
                B[i]=B[i]+sum[tot]*P%mod;
                if(B[i]>=mod)B[i]-=mod;
                int cur=pos[tmp];c=c-tot*P;
                int R=cur+c-1;
                if(R<=tot){
                    B[i]=B[i]+sum[R]-sum[cur-1];
                    B[i]=(B[i]%mod+mod)%mod;
                }else{
                    B[i]=B[i]+sum[tot]-sum[cur-1];
                    B[i]=(B[i]%mod+mod)%mod;
                    c=c-(tot-cur+1);
                    B[i]=B[i]+sum[c];
                    B[i]=(B[i]%mod+mod)%mod;
                }
            }else if(tmp==1){
                B[i]=B[i]+c;
                B[i]%=mod;
            }
        }
        C[now]=true;ans[now]=B[i];
    }
    FWT(B,m,inv);
    printf("%d
",B[v]);
    return 0;
}

QAQ 今天考试是原题大赛

并没有什么好总结的 QAQ

原文地址:https://www.cnblogs.com/joyouth/p/5542501.html