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, &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
", sum);
    else
        printf("%I64d
", 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
", dp[70][0]-1);
    return 0;
}
View Code

D. String Mark

题意

分析


E. Eyes Closed

题意

分析

要么优秀要么生锈
原文地址:https://www.cnblogs.com/Superwalker/p/7903792.html