LA 4270 Discrete Square Roots (扩展欧几里得+模方程)

LA 4270 Discrete Square Roots


题目大意:

在模n的意义下,非负整数x的离散平方根是满足 0r<n 的整数,所以一个x可能会有多个离散平方根.
输入x,n,r( 1x<n,2n109,1rn ),输出数据编号和所有离散平方根,从小到大排序.

题目分析:

(又是一道扩欧的题,orz……)

已知 r2x(mod n) ,则有 r2x=k1n ,设 r2x=k2n
所以 r2r2=k3n ,则有 (r+r)(rr)=k3n

ab=n ,所以

(r+r)(rr)=k3ab
r+ra(mod n),rrb(mod n)

(一开始的时候推导到这里就推不下去了,orz……)

r+r=ax,rr=by
(r+r)+(rr)=ax+by
ax+by=2r

得到一个直线模方程 ax+by=2r ,通过扩欧求解.
因为 ab=n ,所以枚举 n <script type="math/tex" id="MathJax-Element-282">n</script>的因子求解(详见代码).

代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>

using namespace std;

typedef long long ll;

void exgcd(ll a,ll b,ll& g,ll& x,ll& y)
{
    if(!b) g=a,x=1,y=0;
    else exgcd(b,a%b,g,y,x),y-=x*(a/b);
}

ll x,n,r;
set<ll>ans;

void solve(ll a,ll b,ll c)//c=2r
{
    ll g,x,y;
    exgcd(a,b,g,x,y);//ax+by=gcd(a,c)
    if(c%g) return ;
    x*=c/g;//ax+by=c的一组解x0
    b/=g;//b'
    x=(x%b+b)%b;//x的非负整数解,x=x0+kb' 
    ll r=a*x-c/2;//r的一组解,可能为负 
    ll p=a*b;//p=a*b' 因为x=x0+k*b',r=ax+r'=k*a*b'+r'
    while(r<n) {
        if(r>=0) ans.insert(r);
        r+=p;
    }
}

int main()
{
    int kase=0;
    while(scanf("%lld%lld%lld",&x,&n,&r)==3&&n) {
        ans.clear();
        ll m=sqrt(n);
        for(ll i=1;i<=m;i++) if(n%i==0)
            solve(i,n/i,2*r),solve(n/i,i,2*r);
        printf("Case %d:",++kase);
        for(set<ll>::iterator it=ans.begin();it!=ans.end();it++)
            printf(" %lld",*it);
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Supervised Discrete Multi-view Hashing(SDMH)型的代码主要分为以下几个部分:数据处理、型定义、损失函数、优化器、训练和测试。 以下是SDMH型的主要代码解读和注释: ```python # 数据处理 class Dataset(Dataset): def __init__(self, data, num_view): self.data = data self.num_view = num_view def __getitem__(self, index): # 获取数据和标签 x = [self.data[i][index] for i in range(self.num_view)] y = self.data[-1][index] return x, y def __len__(self): return len(self.data[0]) # 型定义 class SDMH(nn.Module): def __init__(self, num_view, bit, num_class): super(SDMH, self).__init__() self.num_view = num_view self.bit = bit self.num_class = num_class # 定义多个视图的哈希函数 self.hash_functions = nn.ModuleList([nn.Linear(4096, bit) for i in range(num_view)]) # 定义多个视图的分类器 self.classifiers = nn.ModuleList([nn.Linear(bit, num_class) for i in range(num_view)]) def forward(self, x): # 计算多个视图的哈希码 hash_codes = [] for i in range(self.num_view): h = self.hash_functions[i](x[i]) b = torch.sign(h) hash_codes.append(b) # 计算多个视图的分类概率 outputs = [] for i in range(self.num_view): c = self.classifiers[i](hash_codes[i]) outputs.append(c) return hash_codes, outputs # 损失函数 class SDMH_Loss(nn.Module): def __init__(self, alpha, beta): super(SDMH_Loss, self).__init__() self.alpha = alpha self.beta = beta def forward(self, hash_codes, outputs, y): # 计算哈希码之间的欧氏距离 dist = 0 for i in range(len(hash_codes)): for j in range(i+1, len(hash_codes)): dist += torch.pow(torch.norm(hash_codes[i]-hash_codes[j]), 2) # 计算标签之间的汉明距离 label_dist = torch.pow(torch.norm(y.unsqueeze(1)-y.unsqueeze(0), p=0), 2) # 计算损失函数 loss = torch.sum(torch.stack(outputs, dim=0)) + self.alpha*dist - self.beta*label_dist return loss # 优化器 optimizer = optim.Adam(sdmh_model.parameters(), lr=0.01) # 训练 for epoch in range(num_epochs): sdmh_model.train() for i, (x, y) in enumerate(train_loader): # 前向传播 hash_codes, outputs = sdmh_model(x) # 计算损失函数 loss = sdmh_loss(hash_codes, outputs, y) # 反向传播 optimizer.zero_grad() loss.backward() optimizer.step() # 测试 with torch.no_grad(): sdmh_model.eval() for i, (x, y) in enumerate(test_loader): # 前向传播 hash_codes, outputs = sdmh_model(x) # 计算准确率 acc = (torch.argmax(torch.sum(torch.stack(outputs, dim=0), dim=0), dim=1) == y).float().mean() print("Accuracy: %.4f" % acc) ``` 注释: - 数据处理:将多个视图的数据和标签打包成一个数据集,每个样本包含多个视图的数据和一个标签。 - 型定义:定义SDMH型,包含多个视图的哈希函数和分类器。每个视图的哈希函数将视图的数据映射到二进制哈希码,每个视图的分类器将哈希码映射到标签的概率分布。 - 损失函数:定义SDMH型的损失函数,包含哈希码之间的欧氏距离和标签之间的汉明距离。目标是最小化损失函数,同时使得哈希码之间的距离尽可能小,标签之间的距离尽可能大。 - 优化器:使用Adam优化器对SDMH型进行参数更新。 - 训练:使用训练数据对SDMH型进行训练,包含前向传播、计算损失函数、反向传播和参数更新。 - 测试:使用测试数据对SDMH型进行测试,包含前向传播、计算准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值