round15

F:问有多少对n个元素的集合A,B满足它们的笛卡尔和恰由1 ~ n2 构成,其中A包含0,B包含1
n<=1012,T<=5000

分析:考虑固定B,如何去确定A;
首先,0在A中,那么所有B中的元素就都在笛卡尔和中;考虑第一个B中没有出现的数x,那么x-1必然在A中(不然1和这个数作用就会重复),然后我们把x-1和B中所有元素再做一遍笛卡尔和;
接着我们再找到第一个和中没有出现过的数x,x-1必然在A中,依此类推,直到穷尽1~ n2
从中可以看出,一个B最多对应一个A;于是我们现在的目标就是找到有多少个合法的B;
再观察B有什么性质
假设1~x都在B中,而x+1不在B中,那么x必然在A中,因而可以推断出x+1~2x都不在B中;进一步k*x+1~(k+1)*x要么都在B中,要么都不在
另一方面,假设2~x都不在B中,而x+1在B中,与上面同理可以得到只有kx+1可能在B中
按照这个思路,我们可以令f(n,m)代表n个数,填满1~n*m,且2必须在B中的方案数;g(n,m)代表n个数,填满1~n*m,且2必须不在B中的方案数;
那么有

f(n,m)=d|n,d>1g(nd,m)

g(n,m)=d|m,d>1f(n,md)

一个惊人的关系是f(n,m)=g(m,n),可以用数学归纳法简单证明
由此可以导出
f(n,m)=d|n,d>1f(m,nd)

而我们要算的答案即 h(n,n)=f(n,n)+g(n,n)=2f(n,n)
鉴于数据范围巨大,当前的式子还不足以解决这个问题;另一个观察是f(n,m)只与n,m的因子构成有关;因此因子构成相同的可以只算一次;用dfs爆搜所有不同的因子构成,发现只有<5000个状态;因而可以把这5000个答案本地打表出来,这样复杂度就只剩下因式分解的复杂度;为了本地打表我利用了推导出的另一个公式
h(n,m)=d|n,d>1μ(d)h(nd,m)+d|m,d>1μ(d)h(n,md)

由于 μ 函数的特殊性,我们可以预处理出一张转移表来加速;另外h(n,m)=h(m,n),因而我们可以只算一半;这样使得总计算次数在 109 左右,可以跑出结果;
为了节省时间,我采用的是<100w预处理,>100wPollard-rho分解的方法;但我发现仍然很慢TAT

总结:这题我想了很久,就是最后没有想到因子同构QAQ

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<vector>
#include<string.h>
#include<math.h>
#include<assert.h>
using namespace std;
typedef long long LL;
const int Maxn=1000002,Maxstate=5000;
const LL M=10000000061LL,totlim=1e12+2;
typedef pair<int,int>pi;

LL a[Maxn];
map<pi,LL>mpF,mpG;
LL calF(int n,int m);
LL tot=0;
map<vector<int>,int >Id;
vector<int>All[5000];
vector<pi>G[5000];
LL dp[100][100];


bool isp[Maxn];
int least[Maxn];
vector<int>pri;
void getp(){
    for(int i=2;i<Maxn;i++){
        if(!isp[i])pri.push_back(i),least[i]=i;
        for(int j=0;j<pri.size()&&pri[j]*i<Maxn;j++){
            isp[pri[j]*i]=1;
            least[pri[j]*i]=pri[j];
            if(i%pri[j]==0){break;}
        }
    }
}
vector<LL>yinzi;
LL mul(LL a,LL b,LL n){return (a*b-(LL)(a/(long double)n*b+1e-3)*n+n)%n;}
LL powmod(LL x,LL y,LL mod){
    LL ret=1;
    x%=mod;
    while(y){
        if(y&1)ret=mul(ret,x,mod);
        y>>=1;
        x=mul(x,x,mod);
    }
    return ret;
}
bool check(LL a,LL n){
    LL m=n-1;
    int s=0;
    while(~m&1)m>>=1,s++;
    LL x=powmod(a,m,n);
    for(int i=1;i<=s;i++){
        LL y=mul(x,x,n);
        if(y==1&&x!=1&&x!=n-1)return 0;
        x=y;
    }
    return x==1;
}
LL Miller_Rabin(LL x){
    if(x==1)return 0;
    if(x==2)return 1;
    if(~x&1)return 0;
    int times=3;//Pro=1/4^times
    while(times--)if(!check(rand()%(x-2)+2,x))return 0;
    return 1;
}
LL Pollard_rho(LL n,int c){
    LL factor=1;
    int cirsize=1;
    LL x=rand()%n,xfixed=x;
    while(factor==1){
        for(int i=0;i<cirsize;i++){
            x=(mul(x,x,n)+c)%n;
            if(x==xfixed)return 1;
            LL d=__gcd(n,(x-xfixed+n)%n);//
            if(d>1&&d<n)return d;
        }
        cirsize<<=1;
        xfixed=x;
    }
    assert(0);
}
void findfac(LL x,int c){
    if(x==1)return;
    if(x<Maxn){
        yinzi.push_back(least[x]);
        findfac(x/least[x],c);
        return;
    }
    if(Miller_Rabin(x)){//ispri
        yinzi.push_back(x);
        return;
    }
    LL tmp;
    while((tmp=Pollard_rho(x,c--))==1);
    findfac(x/tmp,c);findfac(tmp,c);
}
void dfs(LL n,vector<int>&V){//n<m
    All[Id.size()]=V;
    int tmp=Id.size();
    Id[V]=tmp;
    int bef=V.size()?V.back():60;
    for(int i=1;i<=bef;i++){
        if(n*pri[V.size()]>=totlim)break;
        n*=pri[V.size()];
        V.push_back(i);
        dfs(n,V);
        V.pop_back();
    }
}
void precal(){
    for(int i=0;i<Id.size();i++){
        for(int mask=1;mask<1<<All[i].size();mask++){
            vector<int>t=All[i];
            for(int k=0;k<t.size();k++){
                if(mask>>k&1){
                    t[k]--; 
                }
            }
            sort(t.begin(),t.end(),greater<int>());
            while(t.size()&&!t.back())t.pop_back();
            G[i].push_back(pi(Id[t],__builtin_popcount(mask)&1?1:-1));
        }
    }
    LL tot=0;
    for(int i=0;i<Id.size();i++){
        for(int j=i;j<Id.size();j++){
            if(i==0&&j==0)dp[i][j]=1;
            else dp[i][j]=0;
            for(int k=0;k<G[i].size();k++){
                int nxt=G[i][k].first,flag=G[i][k].second;
                dp[i][j]+=dp[nxt][j]*flag;
                dp[i][j]%=M;
                tot++;
            }
            for(int k=0;k<G[j].size();k++){
                int nxt=G[j][k].first,flag=G[j][k].second;
                dp[i][j]+=dp[min(nxt,i)][max(nxt,i)]*flag;
                dp[i][j]%=M;
                tot++;
            }
        }
    }
    for(int i=0;i<Id.size();i++)printf("%lldLL,",(dp[i][i]+M)%M);
}
map<LL,vector<int> >have;
int main(){
    //freopen("mysol.txt","w",stdout);
    getp();
    vector<int>State;
    dfs(1,State);
    //precal();
    int cas=1;
    //return 0;
    int _;scanf("%d",&_);
    while(_--){
        LL x;scanf("%lld",&x);
        vector<int>V;
        if(have.find(x)!=have.end())V=have[x];
        else{
            yinzi.clear();
            findfac(x,2730);        
            sort(yinzi.begin(),yinzi.end());
            for(int i=0,j;i<yinzi.size();i=j){
                for(j=i+1;j<yinzi.size()&&yinzi[i]==yinzi[j];j++);
                V.push_back(j-i);
            }
            sort(V.begin(),V.end(),greater<int>());
            have[x]=V;
        }
        printf("Case #%d: %lld\n",cas++,sol[Id[V]]);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
Round robin是一种常见的调度算法,可以应用于各种领域,包括计算机网络和硬件设计。在Verilog中实现Round robin调度算法需要考虑以下几个方面: 1. 实现一个计数器来跟踪当前正在服务的任务编号。 2. 定义一个任务数组,用于存储需要执行的任务。 3. 在每个时钟周期中,遍历任务数组,并选择下一个任务执行。 4. 如果任务执行完成,则将其从数组中删除。 5. 如果任务数量超过数组大小,则从头开始重新遍历。 以下是一个简单的Round robin实现的Verilog代码示例: ``` module round_robin( input clk, input rst, input [3:0] num_tasks, input [3:0] task_done, output reg [3:0] current_task ); reg [3:0] task_array[15:0]; reg [3:0] task_count; always @ (posedge clk) begin if (rst) begin task_count <= 0; current_task <= 0; end else begin // add new tasks to array for (i = 0; i < num_tasks; i = i + 1) begin if (!task_array[i]) begin task_array[i] <= i; end end // remove completed tasks from array if (task_done != 4'b0000) begin for (i = 0; i < num_tasks; i = i + 1) begin if (task_array[i] == task_done) begin task_array[i] <= 4'b0000; end end end // choose next task to execute if (task_array[task_count]) begin current_task <= task_array[task_count]; end // increment task count if (task_count == num_tasks - 1) begin task_count <= 0; end else begin task_count <= task_count + 1; end end end endmodule ``` 在这个例子中,输入num_tasks表示任务的数量,输入task_done表示完成的任务编号。输出current_task表示当前正在执行的任务编号。在每个时钟周期中,根据计数器的值,从任务数组中选择下一个任务来执行,并在任务完成后从数组中删除。当任务数量超过数组大小时,重新开始遍历。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值