C:
给你n个数和m个数 n , m <= 10^5,每个数 <= 10^7,n个数相乘代表分子,m个数相乘代表分母,现在要把这个分数的最简式也这样子代表出来,也就是说用nout个数代表分子,mout个数代表分母,必须是最简式,每个数的范围都得是 <= 10^7。
思路:
直接统计分子分母的所有素因子的个数,然后消去各个可以消去的素因子即可。
这里我用的筛素数法是O(N)的并且顺便处理出了每个数最小的素因子,这样子的话分解素因子岂不是很简单了。。。复杂度超低nice~
#include
#include
#include
#include
using namespace std;
#define pb push_back
const int maxp = 10000010;
const int maxn = 100000 + 10;
int pri[777777], pnum, minp[maxp];
bool vis[maxp];
int a[maxn], b[maxn], cnt1[maxp], cnt2[maxp];
// O(n)筛素数法,minp[i]表示i的最小的素因子
void get_prime(int n) {
vis[1] = 1; pnum = 0;
for(int i = 2;i <= n; i++) {
if(!vis[i]) {
pri[pnum++] = i;
minp[i] = i;
}
for(int j = 0;j < pnum; j++) {
if(pri[j] * i > n) break;
vis[pri[j] * i] = 1;
minp[pri[j] * i] = pri[j];
if(i % pri[j] == 0) break;
}
}
}
vector
pr1, pr2; int main() { get_prime(10000000); int n, m, mx = 0; scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); mx = max(mx, a[i]); int cur = a[i]; while(cur > 1) { cnt1[minp[cur]] ++; cur /= minp[cur]; } } for(int i = 0;i < m; i++) { scanf("%d", &b[i]); mx = max(mx, b[i]); int cur = b[i]; while(cur > 1) { cnt2[minp[cur]] ++; cur /= minp[cur]; } } for(int i = 1;i <= mx; i++) cnt1[i] = cnt2[i] = min(cnt1[i], cnt2[i]); for(int i = 0;i < n; i++) { int cur = a[i], now = cur; while(cur > 1) { int tmp = minp[cur]; if(cnt1[tmp]) now /= tmp, cnt1[tmp]--; cur /= tmp; } pr1.pb(now); } for(int i = 0;i < m; i++) { int cur = b[i], now = cur; while(cur > 1) { int tmp = minp[cur]; if(cnt2[tmp]) now /= tmp, cnt2[tmp]--; cur /= tmp; } pr2.pb(now); } sort(pr1.begin(), pr1.end()); sort(pr2.begin(), pr2.end()); printf("%d %d\n", n, m); for(int i = 0;i < n; i++) printf("%d ", pr1[i]); puts(""); for(int i = 0;i < m; i++) printf("%d ", pr2[i]); puts(""); return 0; }
D:
直接贪心从a数列中从大到小到从小到大的b数列中选择尽可能多的和 >= x的即可,最好的排名肯定是1的。
E:
要你用m个字母组成n个字母,问有多少种情况,这里有些限制有些字母不能组合。
思路:很裸的矩阵二分幂
#include
#include
#include
using namespace std;
typedef __int64 ll;
const int mod = 1000000007 ;
char s[11];
int pow_mod(int q[55][55], ll n, int m) {
int a[55][55], aa[55][55], qq[55][55];
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++)
a[i][j] = i == j ? 1 : 0;
while(n) {
if(n & 1) {
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++) {
aa[i][j] = 0;
for(int k = 0;k < m; k++)
aa[i][j] = (aa[i][j] + (ll)a[i][k]*q[k][j])%mod;
}
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++)
a[i][j] = aa[i][j];
}
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++) {
qq[i][j] = 0;
for(int k = 0;k < m; k++)
qq[i][j] = (qq[i][j] + (ll)q[i][k]*q[k][j])%mod;
}
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++)
q[i][j] = qq[i][j];
n /= 2;
}
ll ret = 0;
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++)
ret += a[i][j];
return ret%mod;
}
int a[55][55];
int main() {
int m, k;
ll n;
scanf("%I64d%d%d", &n, &m, &k);
for(int i = 0;i < m; i++)
for(int j = 0;j < m; j++)
a[i][j] = 1;
for(int i = 0;i < k; i++) {
scanf("%s", s);
int x, y;
if(s[0] <= 'Z')
x = 26 + s[0] - 'A';
else
x = s[0] - 'a';
if(s[1] <= 'Z')
y = 26 + s[1] - 'A';
else
y = s[1] - 'a';
a[x][y] = 0;
}
printf("%d\n", pow_mod(a, n-1, m));
return 0;
}