Difference(折半枚举,二分)
题意:
f(233,2)=22+32+32=22 x=f(y,K)−y 现在给出x,k 求可能的y有多少个
思路:
0≤x≤10^9 1≤K≤9 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; }