一道题3

$x,y \leq 1e18$,求式子$\sum_{i=0}^{x}C_{\frac{x+y}{2}}^{i}C_{x-i}^{\frac{x+y}{2}} \ \ mod \ \ 1e5+3$。

Lucas定理的高度感性理解是把$mod \ \ p$下的每一位算组合数然后乘起来,因此可以采用一个数位DP的方式算这个式子。

然而比较头疼的是有个减号,涉及退位,因此每一位把$\leq 当前位及更低位组成的数$的值和$>他$的值分开来算,退位时用上一位的$>$计算,不退位用上一位$\leq$算。

代码很精髓。需反复分析。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<vector>
 6 //#include<queue>
 7 //#include<time.h>
 8 //#include<complex>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 #define LL long long
14 LL X,Y;
15 int f[10],g[10],a[10],la=0,b[10],lb=0;
16 const int mod=1e5+3;
17 int fac[mod+4],inv[mod+4];
18 int powmod(int a,int b) {int ans=1; while (b) {if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b>>=1;} return ans;}
19 int C(int n,int m) {return m>n?0:fac[n]*1ll*inv[m]%mod*inv[n-m]%mod;}
20 int main()
21 {
22     scanf("%lld%lld",&X,&Y);
23     if (X<Y || ((X^Y)&1)) {puts("0"); return 0;}
24     fac[0]=1; for (int i=1;i<=mod;i++) fac[i]=fac[i-1]*1ll*i%mod;
25     inv[mod-1]=powmod(fac[mod-1],mod-2); for (int i=mod-1;i;i--) inv[i-1]=inv[i]*1ll*i%mod;
26     X^=Y^=X^=Y; X=(X+Y)>>1;
27     f[0]=1;
28     LL tmp=X; while (tmp) a[++la]=tmp%mod,tmp/=mod;
29     tmp=Y; while (tmp) b[++lb]=tmp%mod,tmp/=mod;
30     for (int i=1;i<=lb;i++)
31     {
32         for (int j=0;j<mod;j++) if (b[i]>=j) f[i]=(f[i]+1ll*f[i-1]*C(a[i],j)%mod*C(b[i]-j,a[i]))%mod;
33         else g[i]=(g[i]+1ll*f[i-1]*C(a[i],j)%mod*C(b[i]+mod-j,a[i]))%mod;
34         for (int j=0;j<mod;j++) if (b[i]>=j+1) f[i]=(f[i]+1ll*g[i-1]*C(a[i],j)%mod*C(b[i]-j-1,a[i]))%mod;
35         else g[i]=(g[i]+1ll*g[i-1]*C(a[i],j)%mod*C(b[i]+mod-j-1,a[i]))%mod;
36     }
37     printf("%d\n",f[lb]);
38     return 0;
39 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/8607003.html

以下是一道ACM目的示例: 目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能重复使用。 示例 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 解思路 这道可以使用哈希表来解决。哈希表中存储每个数的下标,遍历数组时,判断哈希表中是否存在 target-nums[i],如果存在,则说明找到了符合要求的两个数,返回它们的下标即可。 代码实现 C++代码实现: ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> m; for (int i = 0; i < nums.size(); i++) { int complement = target - nums[i]; if (m.count(complement)) { return {m[complement], i}; } m[nums[i]] = i; } return {}; } int main() { vector<int> nums = {2, 7, 11, 15}; int target = 9; vector<int> res = twoSum(nums, target); for (int i = 0; i < res.size(); i++) { cout << res[i] << " "; } return 0; } ``` Python代码实现: ```python def twoSum(nums, target): d = {} for i, n in enumerate(nums): complement = target - n if complement in d: return [d[complement], i] d[n] = i return [] nums = [2, 7, 11, 15] target = 9 print(twoSum(nums, target)) ``` Java代码实现: ```java import java.util.HashMap; public class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] {map.get(complement), i}; } map.put(nums[i], i); } return new int[] {}; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值