Codeforces Round #448 (Div. 2)
?
B. XK Segments
題意
給n,x,k,再n個數, 找出有多少對?(i,j)并且a[i] <= a[j],使得在? a[i] <= y <= a[j] 中有k個數可以整除x
n,?x,?k?(1?≤?n?≤?105,?1?≤?x?≤?109,?0?≤?k?≤?109),ai?(1?≤?ai?≤?109)?
分析
直接unordered_map存[1,a[i] ]中有多少個能整除k
k!=0的情況很顯然,直接以當前數為左端點,找右端點的個數即可
k==0時,加上和一樣的數,不一樣但整除數一樣的求和/2即可
?
#include<bits/stdc++.h> #define ll long long using namespace std;const int maxn = 1e5 + 10; const ll mod = 1e9 + 7; ll n,x,k; ll a[maxn]; unordered_map<ll,ll>mp; unordered_map<ll,ll>vis;int main() {scanf("%I64d%I64d%I64d\n", &n, &x, &k);for(int i = 1;i <= n; i++){scanf("%I64d", &a[i]);mp[a[i]/x]++;vis[a[i]]++;}ll sum = 0;ll ans=0, num=0;for(int i = 1; i <= n;i++){if((a[i]%x)==0){if(k!=0)sum += mp[k+a[i]/x-1];}else{sum += mp[k+a[i]/x];if(k==0){ans+=vis[a[i]];// mp[k+a[i]/x]-=vis[a[i]];num+=mp[a[i]/x]-vis[a[i]];}}}if(k!=0)printf("%I64d\n", sum);elseprintf("%I64d\n", ans+num/2);return 0; } View Code?
C.Square Subsets
題意
給n個數,問有多少選出任意個數相乘是平方數,答案對1e9+7取模
(1?≤?n?≤?105)? ,ai?(1?≤?ai?≤?70)?
分析
狀壓mask dp
首先一個數是平方數,肯定是若干個素數,并且每個質數是偶數個,所以不難想到,如果將70以內的素數(19個),看成19個二進制位,分別化為s[i],表示每一個數二進制位的情況,如果每一位都是0的話,這個數則為平方數。
定義:dp[i][j]表示前1~i個數,mask位 j 的方案數,則dp[70][0]則為答案
轉移:考慮當前數i,如果能轉移到j,則dp[i][j]=(((dp[i-1][j]+dp[i-1][s[i]^j])%mod)*(fac[cnt[i]-1]))%mod;
組合數C(n,m)從n和數選擇m個數,選擇奇數個和偶數個的總方案數都為2^(n-1),總的為2^n,因為每一個數都有兩種狀態0/1
trick:注意將dp[0][0]設為1,并答案減去1,因為只有所有的數都選0個才不符合情況,顯然這種情況這有一種
?
#include <bits/stdc++.h> #define ll long long using namespace std;const int maxn = 524300 ; const int maxm = 1e5 + 3; const ll mod = 1e9+7;int dp[71][maxn]; int fac[maxm]; int cnt[71]; int prime[21]={2 ,3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67}; int n; int s[71];int main() {for(int i = 1; i <= 70; i++){int ii=i;for(int j = 0; j < 19; j++){while(ii%prime[j] == 0){ii/=prime[j];s[i]^=(1<<j);}}}fac[0]=1;fac[1]=2;for(int i = 2; i <= 100000; i++){fac[i]=(2*fac[i-1])%mod;}scanf("%d", &n);int x;for(int i = 1; i <= n; i++){scanf("%d", &x);cnt[x]++;}dp[0][0]=1;for(int i = 1; i <= 70; i++){if(!cnt[i]){for(int j = 0; j < (1<<19); j++){dp[i][j]=dp[i-1][j];}}else{for(int j = 0; j < (1<<19); j++){dp[i][j]=(((dp[i-1][j]+dp[i-1][s[i]^j])%mod)*(fac[cnt[i]-1]))%mod;}}}printf("%d\n", dp[70][0]-1);return 0; } View Code?
D. String Mark
題意
分析
?
E. Eyes Closed
題意
分析
轉載于:https://www.cnblogs.com/Superwalker/p/7903792.html
總結
以上是生活随笔為你收集整理的Codeforces Round #448 (Div. 2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: excel中如何将时间戳转换为日期格式
- 下一篇: Elasticsearch-集群原理