Difference(折半枚举,二分)

题意:

f(233,2)=22+32+32=22    x=f(y,K)y   现在给出x,k 求可能的y有多少个

思路

0x10^9     1K9       y>10^10时,f(y,k)−y≤0(下面代码是证明过程)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int sum[20][20];
ll fum(ll i){
    ll s=0;
    while(i){
        s=s*10+9;
        i--;
    }
    return s;
}
int main()
{

    for(int i = 1; i < 10; i++)
    {
        sum[i][0] = 1;
        for(int j = 1; j <= 9; j++)
        {
            sum[i][j] = sum[i][j - 1] * i;
        }
    }
    freopen("out.txt", "w", stdout);
    ll i;
    for(i=8;i<=15;i++){
        if(i*sum[9][9]<fum(i)){
            cout<<i<<endl;
            break;
        }

    }
    fclose(stdout);
    return 0;
}

输出10

因为y最长是是个字符,那么就可以把y分成两部分来二分查找(后来知道这种思想叫折半枚举,一部分是前五位,一部分是后五位。

代码:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
int sum[20][20];
int num[100007], a[100007];

int main()
{
    for(int i = 1; i < 10; i++)
    {
        sum[i][0] = 1;
        for(int j = 1; j <= 9; j++)
        {
            sum[i][j] = sum[i][j - 1] * i;
        }
    }
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int T, x, k, temp;
    LL pos;
    cin >> T;
    int mm = 1;
    while(T--)
    {
        LL t;
        pos = 0;
        scanf("%d%d", &x, &k);
        memset(num, 0, sizeof(num));
        for(int i = 1; i < 100000; i++)
        {
            temp = i;
            while(temp)
            {
                num[i] += sum[temp % 10][k];
                temp /= 10;
            }
            a[pos++] = num[i] - i;
        }
        sort(a, a + pos);

        LL ans = 0;
        for(LL i = 0; i < 100000; i++)
        {
            t = num[i] - i * 100000;
            t = x - t;

            temp = lower_bound(a, a + pos, t) - a;
            ans += (upper_bound(a, a + pos, t) - lower_bound(a, a + pos, t));

        }
        printf("Case #%d: ", mm++);
        cout<<ans<<endl;
    }

    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

这个是求n^n模板

int sum[20][20];
for(int i = 1; i < 10; i++)
{
    sum[i][0] = 1;
    for(int j = 1; j <= 9; j++)
    {
        sum[i][j] = sum[i][j - 1] * i;
    }
}

 

Four Operations(思路题)

题意:输入一行仅由1~9组成的字符串 按照+ - * / 对他们进行操作,求结果之后最大值(12345 max= 1+2-3*4/5=1)

思路:a+b最大则结果最大,c和d都是一位,e可以是一位可以是两位。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int sum[20][20];
/*void powerinit(){
for(int i=1;i<10;i++){
        sum[i][0]=1;
        for(int j=1;j<=9;j++){
            sum[i][j]=sum[i][j-1]*i;
        }
    }
}*/
char s[50];
int k[50];
ll fun(int i, int j)
{
    int it;
    ll s = 0;
    for(it = i; it <= j; it++)
    {
        s = s * 10 + k[it];
    }
    return s;
}
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int n, cas, i;
    cin >> n;
    for(cas = 1; cas <= n; cas++)
    {
        cin >> s;
        ll ans=-inf;
        int l=strlen(s);
        for(i = 0; i < l; i++)
        {
            k[i] = s[i] - '0';
        }
        for(i = 1; i < l - 3; i++)
        {
            ll ab, c, d, e;
            ab = max(fun(0, 0) + fun(1, i), fun(0, i - 1) + fun(i, i));
            c = k[i + 1], d = k[i + 2];
            e=fun(i+3,l-1);
            //printf("%lld %lld %lld %lld\n",ab,c,d,e);
            ans=max(ans,ab-c*d/e);

        }
        printf("Case #%d: %lld\n",cas,ans);
    }
    return 0;
}

 Car (精度)

题意:司机开车,速度是一组非递减的序列,然后交警只记录了他的位置,问整段路程的时间

思路:注意精度问题,就是每次用当前的路程除以速度,然后得到时间的整数,如果这个长度除以这个时间整数不能得到这个速度,那就时间加一,然后算出新的时间,更新时间和答案就行了。

#include<bits/stdc++.h>
using namespace std;
#define maxn 100100
#define ll long long
int T,n;

int num[maxn];
int main()
{
    int cas=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        num[0]=0;
        for(int i=1;i<=n;i++)  scanf("%d",&num[i]);

        ll ans=0;
        double spe=num[n]-num[n-1];
        for(int i=n;i>0;i--)
        {
            double len=(num[i]-num[i-1])*1.0;
            int t=len/spe;
            ans+=t;
            if(len/t!=spe)
            {
                ans++;
                spe=len/(t+1);
            }
        }

        printf("Case #%d: %lld\n",++cas,ans);
    }

    return 0;
}

 

ArcSoft's Office Rearrangement(贪心,思路(前缀和←不懂诶QAQ))

题意:

给你N个数,让你分成K个相等的数,操作有两种:

①合并相邻的两个数,得到的数为两个数的和。

②分开一个数,得到的两个数为那个数的拆分。

问最少需要操作多少次。
 
思路:题解说是用前缀和... 不懂诶( 私は马鹿です)    然后就贪心...(大概要笨死了我这个题我做了两个小时)
   求sum=∑a[i]  再求ave=sum/k    a[i]>k 就看能减去多少个k  a[i]<k 就a[i+1]加到a[i]上(不要忘记把最后结果赋给最新的i)  这种操作都要ans++
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
ll a[100005];
/*void powerinit(){for(int i=1;i<10;i++){  sum[i][0]=1;  for(int j=1;j<=9;j++)sum[i][j]=sum[i][j-1]*i; }  }*/
ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}
int main()
{
    freopen("in.txt","r",stdin); 
    freopen("out.txt","w",stdout); 
    int T, cas = 1;
    scanf("%d",&T);
    for(; cas <= T; cas++)
    {
        
        int i,n,k;
        ll s = 0;
        scanf("%d%d",&n,&k);
        memset(a, 0, sizeof(a));
        ll ans = 0;
        for(i = 0; i < n; i++)
        {
            scanf("%lld",&a[i]);
            s += a[i];
        }
        if(s % k != 0)
        {
            ans = -1;
        }
        else
        {
            for(i = 0; i < n;)
            {
                if(a[i] > s / k)
                {
                    while(a[i]>s/k){
                        ans++;
                           a[i]-=s/k;
                    }
                    
                }
                else if(a[i] < s / k)
                {
                    ll t=i;
                    while(a[t] < s / k)
                    {
                        ans++;
                        a[t] += a[i+1];
                        i++;
                        //cout<<"   "<<a[t]<<endl;
                    }
                    a[i]=a[t];
                }
                else
                    i++;
            }
        }
         printf("Case #%d: %lld\n",cas,ans);
    }
    
    return 0;
}