DP中平方的转换
Posted milky-w
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DP中平方的转换相关的知识,希望对你有一定的参考价值。
NOI 2009 管道取珠
……设第 i 种输出序列的产生方式(即不同的操作方式数目)有 ai 个,Σai=C(n+m,n)。求 Σ(ai)²。
直接求 ai 是不好做的,由于平方的存在,可以看做两个人同时玩这个游戏,得到的序列完全相同的个数。
2017/11/01 胡策 T3
一年一度的运动会开始了。有 N 个选手参赛,第 i 个选手有一个能力值 Ai,比赛一共进行了 2^M 天。
在第 j 天 (0?j?2^M−1) 的比赛中,第 i 个选手的得分为 A[i] xor j,然后从大到小排名,排名为 x (x 从 0 开始) 的同学会获得 x^2 的积分。
你需要求出每个同学最后总的积分和 q[i] 模 1e9+7 的结果 p[i]。为了避免输出文件过大,你只要输出 p[i] 的异或和即可。
对于 10% 的数据,M <= 5;
对于 30% 的数据,N <= 100;
对于 50% 的数据,N <= 1000;
对于 100% 的数据,N <= 200000,M <= 30,A[i] < 2^M。
这个题的“得分”和“积分”好坑。。
考虑 x^2 的意义,相当于两个人 (可以相同) 同时排在选手 i 前面的组合数。
考虑异或的性质,两个数的大小取决于二进制中不相同的最高位,而这里异或的是一段连续的数 0~2^(M-1),所以 A 排在 B 前面的天数为 2^M / 2 即 2^(M-1) 天,A 和 C 同时排在 B 前面的天数就是 2^(M-2) 天,因为要使两个二进制数位同时等于 1。对于每个人,求出 f[i] 表示能力值与他不相同的最高位为第 i 位的人数,枚举 i 和 j,累加 f[i] * f[j] * 2^(M-2)。
求 f[i] 的过程可以用 trie。总的复杂度大概是 O(NM^2)。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<map> 6 #define ll long long 7 8 using namespace std; 9 10 const int N=200003; 11 const int mod=1000000007; 12 int n,m,A,ch[N*30][2],tot=0,sz[N*30]; 13 ll ans=0; 14 15 void insert(int A) 16 { 17 int now=0; 18 for (int i=m-1;i>=0;i--) 19 { 20 int x=(A>>i)&1; 21 if (!ch[now][x]) ch[now][x]=++tot; 22 now=ch[now][x]; 23 sz[now]++; //每个节点上的子串个数 24 } 25 } 26 27 void dfs(int x,ll sum,ll num) 28 { 29 ll tmp,size; 30 31 size=sz[ch[x][1]],tmp=0; 32 tmp=size*size%mod*(1<<m-1)%mod; 33 tmp=(tmp+size*num%mod*(1<<m-1)%mod)%mod; 34 if (ch[x][0]) dfs(ch[x][0],(sum+tmp)%mod,num+size); 35 36 size=sz[ch[x][0]],tmp=0; 37 tmp=size*size%mod*(1<<m-1)%mod; 38 tmp=(tmp+size*num%mod*(1<<m-1)%mod)%mod; 39 if (ch[x][1]) dfs(ch[x][1],(sum+tmp)%mod,num+size); 40 41 if (!ch[x][0]&&!ch[x][1]) ans^=sum; 42 } 43 44 map<int,bool> vis; 45 46 int main() 47 { 48 freopen("race.in","r",stdin); 49 freopen("race.out","w",stdout); 50 scanf("%d%d",&n,&m); 51 for (int i=1;i<=n;i++) 52 { 53 scanf("%d",&A); 54 insert(A); 55 if (vis.count(A)) return 0; 56 vis[A]=1; 57 } 58 dfs(0,0,0); 59 printf("%lld",ans); 60 return 0; 61 }
以上是关于DP中平方的转换的主要内容,如果未能解决你的问题,请参考以下文章
[JavaScript 刷题] DP - 组成整数的最小平方数数量, leetcode 279
leetcode 279. Perfect Squares 完全平方数(中等)