kuangbin数论题单
没几道题,却做了很长时间。有几个很水的题,但大部分质量很高,尤其是最后做的三四个题,把我写吐了。
题单地址:[kuangbin带你飞]专题1-23
LightOJ 1370 Bi-shoe and Phi-shoe
筛法得到欧拉函数的值
代码
#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
int euler[2000005];
void getEuler(int n){
euler[1] = 1;
for(int i=2; i<=n; i++){
if(!euler[i]){
for(int j=i; j<=n; j += i){
if(!euler[j]){
euler[j] = j;
}
euler[j] = euler[j]/i*(i-1);
}
}
}
}
int mp[2000005];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getEuler(2000005);
memset(mp, INF, sizeof(mp));
FOR(i, 1, 2000005){
if(euler[i]<=2000000){
mp[euler[i]] = min(mp[euler[i]], i);
}
}
ROF(i, 1500004, 1){
mp[i] = min(mp[i], mp[i+1]);
}
mp[1] = 2;
int T;
cin >> T;
FOR(tt, 1, T){
ll ans = 0;
int n;
cin >> n;
int t;
FOR(i, 1, n){
cin >>t;
//cout << t << " " << mp[t] << endl;
ans += mp[t];
}
printf("Case %d: %lld Xukha\n",tt,ans);
}
return 0;
}
LightOJ 1341 Aladdin and the Flying Carpet
网上很多代码对\(1-b\)进行循环,复杂度是不正确的。由于\(a\)的素因数最多只有\(\log_{2}a\)个。设\(a=p_1^{k_1}p_1^{k_2}...p_1^{k_n}\),由基本不等式\(k_1k_2..k_n<=(\frac{k_1+k_2...+k_n}{n})^2<=(\frac{\log_{2}a}{n})^2\),可知a的所有素因数个数的乘积不会太大,所以可以用\(dfs\)枚举\(a\)所有可能的因数。
代码
#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int MAXN=1000000;
// 素数筛选
int prime[MAXN+1];
void getPrime(){
for(int i=2; i<=MAXN; i++){
if(!prime[i]) prime[++prime[0]]=i;
for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++){
prime[prime[j]*i] = 1;
if(i%prime[j]==0) break;
}
}
}
// 合数分解
ll factor[100][2];
int factCnt;
void getFactors(ll x){
ll temp = x;
factCnt = 0;
for(int i=1; i<=prime[0] && prime[i]<=temp/prime[i]; i++){ //cout << i << " " << temp << endl;
factor[factCnt][1] = 0;
if(temp%prime[i]==0){
factor[factCnt][0] = prime[i];
while(temp%prime[i]==0){
factor[factCnt][1]++;
temp /= prime[i];
}
factCnt++;
}
}
if(temp!=1){
factor[factCnt][0] = temp;
factor[factCnt++][1] = 1;
}
}
ll a, b;
ll ans;
void dfs(ll now, ll tot){
if(now==factCnt){
if(tot*tot!=a && tot>=b && a/tot>=b) {
ans++;
}
return;
}
ll temp = 1;
FOR(i, 0, factor[now][1]){
tot *= temp;
dfs(now+1, tot);
tot /= temp;
temp *= factor[now][0];
}
return;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getPrime();
int T;
cin >> T;
FOR(tt, 1, T){
ans = 0;
cin >> a >> b;
getFactors(a);
dfs(0, 1);
ans /= 2;
printf("Case %d: %d\n", tt, ans);
}
return 0;
}
LightOJ 1336 Sigma Function
将题目所给公式化简为\(\sigma(n)=(1+p_1+..+p_1^{e_1})(1+p_2+..+p_2^{e_2})...(1+p_k+..+p_k^{e_k})\),如果要让\(\sigma(n)\)为奇数,由于当\(p_k\)为2时,\((1+p_k+..+p_k^{e_k})\)一定为奇数,所以剩下的素因子的指数应该都是偶数,这样当2的指数也是偶数时,\(n\)是某个数的平方。当2的指数是奇数时,如果其余素因子的指数是偶数,应该有\(n/2\)是某个数的平方。综上\(\sigma(n)\)是奇数的条件就是\(n\)是某个数的平方或\(n/2\)是某个数的平方。这个题即输出\(n-\sqrt{n}-\sqrt{n/2}\)
代码
#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=100000;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t;
cin >> t;
FOR(i, 1, t){
ll n;
cin >> n;
n -= (ll)sqrt(n)+(ll)sqrt(n/2);
cout << "Case " << i << ": " << n << endl;
}
return 0;
}
LightOJ 1282 Leading and Trailing
后三位用快速幂对\(n^k\)模1000就可以了。计算前三位时把原数变形为\(n^k=10^{\log_{10}a^k}=10^{k\log_{10}a}\),用\(x,y\)表示\(k\log_{10}a\)的整数部分与小数部分,可得\(n^k=10^{x+y}=10^x*10^y\),则\(n^k\)的位数是由\(10^x\)决定的,各位数字是由\(10^y\)决定的,而\(0\leq y<1\),所以\(1\leq 10^y<10\),\(10^y *100\)的整数部分就是\(n^k\)的前三位。
代码
#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=100000;
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0){
if(n&1) res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
FOR(tt, 1, T){
ll n, k;
cin >> n >> k;
ll ans2 = mod_pow(n, k, 1000);
double ans1 = k*log10(n);
ans1 = fmod(ans1, 1);
cout << "Case " << tt << ": " << (int)(pow(10, ans1)*100) << " ";
cout << setw(3) << setfill('0') << ans2 << endl;
}
return 0;
}
LightOJ 1259 Goldbach`s Conjecture
把1e7以内的素数先筛出来,之后每个数枚举一下就行了。
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
//n以内素数个数
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
int p=0;
for(int i=0;i<=n;i++) is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=n;i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
}
}
return p;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
int all = sieve(10000000);
FOR(tt, 1, T){
int x;
cin >> x;
int ans = 0;
for(int i=0; i<all; i++){
if(prime[i]>x/2) break;
if(is_prime[x-prime[i]]) ans++;
}
cout << "Case " << tt << ": " << ans << endl;
}
return 0;
}
LightOJ 1245 Harmonic Number (II)
数论分块
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
FOR(tt, 1, T){
ll n;
cin >> n;
ll ans = 0;
for(ll l=1, r; l<=n; l=r+1){
r = n/(n/l);
ans += (r-l+1)*(n/l);
}
printf("Case %d: %lld\n", tt, ans);
}
return 0;
}
LightOJ 1236 Pairs Forming LCM
设\(n=p_1^{k_1}p_2^{k_2}...p_m^{k_m}\),由上述式子不难得出\(\forall 1\leq i,j\leq n\),使\(lcm(i,j)=n\)的方案数有\(sum=(2*k_1+1)(2*k_2+1)...(2*k_m+1)\)种,而本题要求\(1\leq i\leq j\leq n\),所以方案数为\((sum+1)/2\)(分子加一是考虑到\(i=j\)的情况)
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int prime[maxn+1];
void getPrime(){
memset(prime, 0 ,sizeof(prime));
for(int i=2; i<=maxn; i++){
if(!prime[i]) prime[++prime[0]] = i;
for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
prime[prime[j]*i] = 1;
if(j%prime[j]==0) break;
}
}
}
ll factor[100][2];
int factCnt;
int getFactors(ll x){
factCnt = 0;
ll temp = x;
for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
factor[factCnt][1] = 0;
if(temp%prime[i]==0){
factor[factCnt][0] = prime[i];
while(temp%prime[i]==0){
factor[factCnt][1]++;
temp /= prime[i];
}
factCnt++;
}
}
if(temp!=1){
factor[factCnt][0] = temp;
factor[factCnt++][1] = 1;
}
return factCnt;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getPrime();
int T;
cin >> T;
FOR(tt, 1, T){
ll n;
cin >> n;
ll ans = 1;
getFactors(n);
for(int i=0; i<factCnt; i++){
ans *= 2*factor[i][1]+1;
}
ans = (ans+1)/2;
printf("Case %d: %I64d\n", tt, ans);
}
return 0;
}
LightOJ 1234 Harmonic Number
直接暴力可以跑出来,但是数组开不到1e8,可以每50个数分一块,这样每次查询最多再跑49次就可以了。
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
double sum[20000005];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
double temp;
FOR(i, 1, 100000000){
temp = 0;
FOR(j, 1, 50){
temp += 1/(double)i;
i++;
}
i--;
sum[i/50] = sum[i/50-1]+temp;
}
int T;
cin >> T;
FOR(tt, 1, T){
ll n;
cin >> n;
double ans = sum[n/50];
ROF(i, n, n-n%50+1) ans += 1/(double)i;
printf("Case %d: %.10f\n", tt, ans);
}
return 0;
}
LightOJ 1220 Mysterious Bacteria
唯一分解定理后取指数项最小值即可。注意当n为负数时,答案一定为奇数,所以要将结果一直除二直到变为奇数。
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int prime[maxn+1];
void getPrime(){
memset(prime, 0 ,sizeof(prime));
for(int i=2; i<=maxn; i++){
if(!prime[i]) prime[++prime[0]] = i;
for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
prime[prime[j]*i] = 1;
if(j%prime[j]==0) break;
}
}
}
ll factor[100][2];
int factCnt;
int getFactors(ll x){
factCnt = 0;
ll temp = x;
for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
factor[factCnt][1] = 0;
if(temp%prime[i]==0){
factor[factCnt][0] = prime[i];
while(temp%prime[i]==0){
factor[factCnt][1]++;
temp /= prime[i];
}
factCnt++;
}
}
if(temp!=1){
factor[factCnt][0] = temp;
factor[factCnt++][1] = 1;
}
return factCnt;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getPrime();
int T;
cin >> T;
FOR(tt, 1, T){
ll n;
cin >> n;
getFactors(abs(n));
int ans = INF;
FOR(i, 0, factCnt-1){
ans = min(1ll*ans, factor[i][1]);
}
if(n<0) while(ans%2==0) ans /= 2;
printf("Case %d: %d\n", tt, ans);
}
return 0;
}
LightOJ 1214 Large Division
高精度模板
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 500;
struct bign{
int d[maxn], len;
void clean() { while(len > 1 && !d[len-1]) len--; }
bign() { memset(d, 0, sizeof(d)); len = 1; }
bign(int num) { *this = num; }
bign(char* num) { *this = num; }
bign operator = (const char* num){
memset(d, 0, sizeof(d)); len = strlen(num);
for(int i = 0; i < len; i++) d[i] = num[len-1-i] - '0';
clean();
return *this;
}
bign operator = (int num){
char s[20]; sprintf(s, "%d", num);
*this = s;
return *this;
}
bign operator + (const bign& b){
bign c = *this; int i;
for (i = 0; i < b.len; i++){
c.d[i] += b.d[i];
if (c.d[i] > 9) c.d[i]%=10, c.d[i+1]++;
}
while (c.d[i] > 9) c.d[i++]%=10, c.d[i]++;
c.len = max(len, b.len);
if (c.d[i] && c.len <= i) c.len = i+1;
return c;
}
bign operator - (const bign& b){
bign c = *this; int i;
for (i = 0; i < b.len; i++){
c.d[i] -= b.d[i];
if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
}
while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
c.clean();
return c;
}
bign operator * (const bign& b)const{
int i, j; bign c; c.len = len + b.len;
for(j = 0; j < b.len; j++) for(i = 0; i < len; i++)
c.d[i+j] += d[i] * b.d[j];
for(i = 0; i < c.len-1; i++)
c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
c.clean();
return c;
}
bign operator / (const bign& b){
int i, j;
bign c = *this, a = 0;
for (i = len - 1; i >= 0; i--)
{
a = a*10 + d[i];
for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
c.d[i] = j;
a = a - b*j;
}
c.clean();
return c;
}
bign operator % (const bign& b){
int i, j;
bign a = 0;
for (i = len - 1; i >= 0; i--)
{
a = a*10 + d[i];
for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
a = a - b*j;
}
return a;
}
bign operator += (const bign& b){
*this = *this + b;
return *this;
}
bool operator <(const bign& b) const{
if(len != b.len) return len < b.len;
for(int i = len-1; i >= 0; i--)
if(d[i] != b.d[i]) return d[i] < b.d[i];
return false;
}
bool operator >(const bign& b) const{return b < *this;}
bool operator<=(const bign& b) const{return !(b < *this);}
bool operator>=(const bign& b) const{return !(*this < b);}
bool operator!=(const bign& b) const{return b < *this || *this < b;}
bool operator==(const bign& b) const{return !(b < *this) && !(b > *this);}
string str() const{
char s[maxn]={};
for(int i = 0; i < len; i++) s[len-1-i] = d[i]+'0';
return s;
}
};
istream& operator >> (istream& in, bign& x)
{
string s;
in >> s;
x = s.c_str();
return in;
}
ostream& operator << (ostream& out, const bign& x)
{
out << x.str();
return out;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
FOR(tt, 1, T){
bign a,b;
cin >> a >> b;
if(a.d[a.len-1]<0) a.d[a.len-1] = 0, a.len--;
if(b.d[b.len-1]<0) b.d[b.len-1] = 0, b.len--;
if(a%b!=bign(0)) printf("Case %d: not divisible\n", tt);
else printf("Case %d: divisible\n", tt);
}
return 0;
}
LightOJ 1213 Fantasy of a Summation
推式子,\(res=kn^{k-1}sum\)
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
// const ll mod = 1e9+7;
const int maxn = 500005;
int casecnt;
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0){
if(n&1) res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
while(T--){
ll n, k, mod, sum = 0;
cin >> n >> k >> mod;
FOR(i, 1, n){
ll x;
cin >> x;
sum = (sum+x)%mod;
}
sum = mod_pow(n, k-1, mod)*k%mod*sum%mod;
printf("Case %d: %lld\n", ++casecnt, sum);
}
return 0;
}
LightOJ 1197 Help Hanzo
区间素数模板
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
int casecnt;
int prime[maxn+1];
void getPrime(){
memset(prime, 0 ,sizeof(prime));
for(int i=2; i<=maxn; i++){
if(!prime[i]) prime[++prime[0]] = i;
for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
prime[prime[j]*i] = 1;
if(j%prime[j]==0) break;
}
}
}
bool notprime[maxn];
int prime2[maxn];
void getPrime2(int l, int r){
memset(notprime, false, sizeof(notprime));
if(l<2) l = 2;
for(int i=1; i<=prime[0]&&(ll)prime[i]*prime[i]<=r; i++){
int s = l/prime[i]+(l%prime[i]>0);
if(s==1) s=2;
for(int j=s; (ll)j*prime[i]<=r; j++){
if((ll)j*prime[i]>=l){
notprime[j*prime[i]-l] = true;
}
}
}
prime2[0] = 0;
for(int i=0; i<=r-l; i++){
if(!notprime[i]){
prime2[++prime2[0]] = i+l;
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getPrime();
int T;
cin >> T;
while(T--){
int l, r;
cin >> l >> r;
getPrime2(l, r);
printf("Case %d: %d\n", ++casecnt, prime2[0]);
}
return 0;
}
LightOJ 1138 Trailing Zeroes (III)
\(n!\)后几位中0的个数其实就是\(n!\)因数中\(5\)的个数,不难推出对于一个确定的n,\(n!\)中后几位0的个数为\(\frac{n}{5}+\frac{n}{5^2}+\frac{n}{5^3}+...\)
二分答案即可
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
int casecnt;
ll fun(ll m){
ll temp = 0;
while(m){
temp += m;
m /= 5;
}
return temp;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
while(T--){
ll n;
cin >> n;
ll l = 0, r = 1e8;
while(r-l>1){
ll mid = (l+r)>>1;
if(fun(mid)>n) r = mid;
else l = mid;
}
cout << "Case " << ++casecnt << ": ";
if(fun(l)==n) cout << 5*l << endl;
else cout << "impossible\n";
}
return 0;
}
UVA 11426 GCD - Extreme (II)
筛出欧拉函数后分块计算即可
代码
#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
// 筛法
int euler[4000005];
void getEuler(int n){
euler[1] = 1;
for(int i=2; i<=n; i++){
if(!euler[i]){
for(int j=i; j<=n; j += i){
if(!euler[j]){
euler[j] = j;
}
euler[j] = euler[j]/i*(i-1);
}
}
}
}
ll sum[4000005];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getEuler(4000002);
FOR(i, 1, 4000001) sum[i] = sum[i-1]+euler[i];
ll n;
while(cin >> n && n){
ll ans = 0;
for(int l=1, r; l<=n; l=r+1){
r = n/(n/l);
ans += (sum[r]-sum[l-1])*(n/l)*(n/l);
}
ans = (ans-n*(n+1)/2)/2;
cout << ans << endl;
}
return 0;
}
POJ 1061 青蛙的约会
题目即求\(x-y+p(m-n)=qL\),转化为\((m-n)x+Ly=y-x\quad(m>n)\)形式用\(exgcd\)求出x的最小正整数解即可。
代码
#define LOCAL
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=1005;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
ll d=a;
if(b!=0){
d=extgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else{
x=1;y=0;
}
return d;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ll x, y, m, n, l;
cin >> x >> y >> m >> n >> l;
ll p, q, d;
if(m<n){
swap(x, y);
swap(m, n);
}
d = extgcd(m-n, l, p, q);
if((y-x)%d) cout << "Impossible\n";
else{
p *= (y-x)/d;
p %= l/d;
p = (p+l/d)%(l/d);
cout << p << endl;
}
return 0;
}
POJ 2115 C Looooops
和上一个题差不多,注意直接使用\(1<<k\)会造成溢出。
代码
#define LOCAL
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=1005;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
ll d=a;
if(b!=0){
d=extgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else{
x=1;y=0;
}
return d;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ll a, b, c, k;
while(cin >> a >> b >> c >> k){
if(a+b+c+k==0) break;
ll m = (1ll<<k);
ll x, y;
ll d = extgcd(c, m, x, y);
if((b-a)%d){
cout << "FOREVER\n";
}
else{
x *= (b-a)/d;
x %= m/d;
x = (x+m/d)%(m/d);
cout << x << endl;
}
}
return 0;
}
HDU 2161 Primes
注意n小于等于零时结束输入
代码
#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
//n以内素数个数
const int maxn=1000000;
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
int p=0;
for(int i=0;i<=n;i++) is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=n;i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
}
}
return p;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
sieve(100000);
is_prime[2] = false;
int T = 0;
int n;
while(cin >> n && n>0){
if(is_prime[n]) printf("%d: yes\n", ++T);
else printf("%d: no\n", ++T);
}
return 0;
}
UVA 11827 Maximum GCD
数论题单的题考输入,就挺离谱的
代码
#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
int gcd(int a, int b){
return b==0? a: gcd(b, a%b);
}
char s[300000];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
getchar();
while(T--){
int ans = 0;
int a[105];
int m = 0;
gets(s);
for(int i=0; i<(int)strlen(s); i++){
int sum = 0;
if(isdigit(s[i])){
while(isdigit(s[i])){
sum = sum*10 + s[i] - '0';
i++;
}
a[++m] = sum;
}
}
FOR(i, 1, m){
FOR(j, 1, m){
if(i!=j){
ans = max(ans, gcd(a[i], a[j]));
}
}
}
cout << ans << endl;
}
return 0;
}
SGU 106 The equation
扩欧求一组解后,根据其解集的形式,解出来两个\(k\)的范围,取个交集就可以了
代码
#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
ll d=a;
if(b!=0){
d=extgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else{
x=1;y=0;
}
return d;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ll a, b, c;
ll l1, l2, r1, r2, L1, L2, R1, R2;
L1 = L2 = -INF;
R1 = R2 = INF;
cin >> a >> b >> c;
cin >> l1 >> r1 >> l2 >> r2;
if(a==0 && b==0){
if(c==0) cout << (r1-l1+1)*(r2-l2+1);
else cout << 0;
cout << endl;
return 0;
}
ll x, y;
c *= -1;
ll d = extgcd(a, b, x, y);
if(c%d){
cout << 0;
return 0;
}
x *= c/d;
y *= c/d;
b /= d;
a /= d;
if(b>0){
L1 = ceil(1.0*(l1-x)/b);
R1 = floor(1.0*(r1-x)/b);
}
else if(b<0){
R1 = floor(1.0*(l1-x)/b);
L1 = ceil(1.0*(r1-x)/b);
}
if(a>0){
L2 = ceil(1.0*(l2-y)/a);
R2 = floor(1.0*(r2-y)/a);
}
else if(a<0){
R2 = floor(1.0*(l2-y)/a);
L2 = ceil(1.0*(r2-y)/a);
}
if(a){
swap(L2, R2);
L2 *= -1;
R2 *= -1;
}
l1 = max(L1, L2);
r1 = min(R1, R2);
if(l1>r1) cout << 0 << endl;
else cout << r1-l1+1 << endl;
return 0;
}
POJ 2478 Farey Sequence
欧拉函数
代码
#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
// 筛法
int euler[1000005];
ll sum[1000005];
void getEuler(int n){
euler[1] = 1;
for(int i=2; i<=n; i++){
if(!euler[i]){
for(int j=i; j<=n; j += i){
if(!euler[j]){
euler[j] = j;
}
euler[j] = euler[j]/i*(i-1);
}
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getEuler(1000005);
FOR(i, 2, 1000000){
sum[i] = sum[i-1]+euler[i];
}
int n;
while(cin >> n && n){
cout << sum[n] << endl;
}
return 0;
}
UVA 11752 The Super Powers
这个处理精度好恶心。。
代码
#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef unsigned long long ll;
const ll mod = 1e9+7;
//n以内素数个数
const int maxn=1000000;
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
int p=0;
for(int i=0;i<=n;i++) is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=n;i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
}
}
return p;
}
vector<ll> ans;
map<ll, bool> ok;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
sieve(1000005);
ans.pb(1);
ll mx = 1ll*18446744073709551615;
for(ll i=2; i<=(1<<16); i++){
ll base = i;
for(int j=2; j<=100; j++){
base *= i;
if(is_prime[j]){
if(base>mx/i) break;
continue;
}
if(!ok[base]){
ok[base] = true;
ans.pb(base);
}
if(base>mx/i) break;
}
}
sort(ALL(ans));
for(auto x:ans) cout << x << endl;
return 0;
}
UVA 10200 Prime Time
计算结果加上1e-8可以避免0.50000被计算成0.499999的问题
代码
#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef unsigned long long ll;
const ll mod = 1e9+7;
bool judge(int x){
for(int i=2; i*i<=x; i++){
if(x%i==0) return false;
}
return true;
}
map<int, int> sum;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
//sum[0] = 1;
FOR(i, 0, 10000){
sum[i] = sum[i-1]+judge(i*i+i+41);
}
int a, b;
while(cin >> a >> b){
printf("%.2f\n", (double)(sum[b]-sum[a-1])/(b-a+1)*100+1e-8);
}
return 0;
}
UVA 11916 Emoogle Grid
当一个格子在第一行或者上方不能染色时,该格子染色方案为\(k\),否则为\(k-1\)。可以分别统计这两种格子的数目\(num1,num2\),则答案为\(r=k^{num1}*(k-1)^{num2}\)
先令\(m\)为不能染色的格子行数的最大值\(max\)(也就是行数可能的最小值),计算一次结果,如果和\(r\)不一样,再假设行数为\(max+1\),如果计算出来的答案\(ans2\)还和\(r\)不一样,之后每增加一行,就相当于多\(n\)个格子染\(k-1\)个颜色,有式子\(r=ans2*((k-1)^{n})^{x}\),用\(BSGS\)算法求出来x,答案即为\(max+x+1\)
这题我一个人wa了一整页,好丢人。。。
代码
#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
//#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
// 哈希BSGS O(sqrt(n)) a^x=b (mod n) a,n互质
#define MOD 76543
ll hs[MOD], head[MOD], Next[MOD], id[MOD], top;
void insert(ll x, ll y){
ll k = x%MOD;
hs[top] = x, id[top] = y, Next[top] = head[k], head[k] = top++;
}
ll find(ll x){
ll k = x%MOD;
for(ll i=head[k]; i!=-1; i=Next[i]){
if(hs[i]==x){
return id[i];
}
}
return -1;
}
ll BSGS(ll a, ll b, ll n){
memset(head, -1, sizeof(head));
top = 1;
if(b==1) return 0;
ll m = sqrt(n*1.0), j;
ll x = 1, p = 1;
for(ll i=0; i<m; i++, p=p*a%n) insert(p*b%n, i);
for(ll i=m; ; i+=m){
if((j=find(x=x*p%n))!=-1) return i-j;
if(i>n) break;
}
return -1;
}
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0){
if(n&1) res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ll T, _=0;
cin >> T;
while(T--){
printf("Case %lld: ", ++_);
ll n, k, b, r;
cin >> n >> k >> b >> r;
map<ll, map<ll, bool> > mp;
vector<ll> x(b+1), y(b+1);
ll mx = 1;
FOR(i, 1, b){
cin >> x[i] >> y[i];
mp[x[i]][y[i]] = true;
mx = max(mx, x[i]);
}
ll num1 = n, num2 = n*(mx-1);
FOR(i, 1, b){
if(x[i]==1){
num1--;
}
else{
num2--;
}
if(x[i]+1<=mx && !mp[x[i]+1][y[i]]) num2--, num1++;
}
ll base = mod_pow(k, num1, mod)*mod_pow(k-1, num2, mod)%mod;
if(base==r){
cout << mx << endl;
continue;
}
num1 = n, num2 = n*mx;
FOR(i, 1, b){
if(x[i]==1){
num1--;
}
else{
num2--;
}
if(!mp[x[i]+1][y[i]]) num2--, num1++;
}
base = mod_pow(k, num1, mod)*mod_pow(k-1, num2, mod)%mod;
ll ans = BSGS(mod_pow(k-1, n, mod), r*mod_pow(base, mod-2, mod)%mod, mod);
cout << ans+mx+1 << endl;
}
return 0;
}
POJ 2116 Death to Binary?
将一个整数转化为\(canonical\ Fibonacci\ representation\)其实就是从大到小遍历斐波那契数,如果当前数字大于这个斐波那契数就减去它并且这一位表示为1否则表示为0。这道题一个数字最多就四十一位,所以从第四十一个斐波那契数开始遍历就行了。写两个函数,一个把斐波那契形式数字(字符串)转化为一个整数,一个把一个整数转化为斐波那契形式的字符串,之后的操作就很简单了
比较坑的是这个题\(fib[0]=1,fib[1]=2\)。还有当数字是0的时候,转化成字符串时要注意一下。
代码
#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
//#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
int fib[45];
int toNum(string s){
int ans = 0;
FOR(i, 0, s.length()-1){
ans += fib[i]*(s[s.length()-1-i]-'0');
}
return ans;
}
string toString(int x){
string s = "";
ROF(i, 43, 0){
if(x>=fib[i]){
x -= fib[i];
s += "1";
}
else if(s!=""){
s += "0";
}
}
if(s=="") s = "0";
return s;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
fib[0] = 1;
fib[1] = 2;
FOR(i, 2, 43) fib[i] = fib[i-1]+fib[i-2];
string x, y;
while(cin >> x >> y){
int a = toNum(x);
int b = toNum(y);
int c = a+b;
string p = toString(a), q = toString(b), r = toString(c);
int w = r.length();
FOR(i, 1, r.length()-p.length()+2) cout << " ";
cout << p << endl;
cout << "+";
FOR(i, 1, r.length()-q.length()+1) cout << " ";
cout << q << endl;
cout << " ";
FOR(i, 1, r.length()) cout << "-";
cout << endl;
cout << " " << r << endl << endl;
}
return 0;
}
UVA 11754 Code Feat
要计算出结果有两种做法,一个是dfs枚举所有余数组合再用中国剩余定理求解,另一种是选定一个除数x,对于他对应的余数r,枚举\(kx+r\)并筛选出符合条件的解
这两种方法交上去亲测都会TLE,第一种方法适用于余数较少的情况,第二种方法适用于余数较多的情况,所以可以根据余数的数量来选择不同的方式求解
代码
#define LOCAL
#include<iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
ll c, s;
ll x[15], b[15], t[11], k[11][105], bst, fact;
vector<ll> ans;
set<ll> st[15];
void sol2(){
sort(k[bst]+1, k[bst]+t[bst]+1);
for(ll i=0; s; i++){
FOR(j, 1, t[bst]){
bool ok = true;
ll tmp = k[bst][j]+x[bst]*i;
if(tmp==0) continue;
FOR(p, 1, c){
if(!st[p].count(tmp%x[p])){
ok = false;
break;
}
}
if(ok){
cout << tmp << endl;
s--;
if(!s) return;
}
}
}
}
ll extgcd(ll aa,ll bb,ll &xx,ll &yy)
{
ll d=aa;
if(bb!=0){
d=extgcd(bb,aa%bb,yy,xx);
yy-=(aa/bb)*xx;
}
else{
xx=1;yy=0;
}
return d;
}
void CRT(){
ll res=0;
FOR(i, 1, c){
ll m = fact/x[i];
ll inv, y;
extgcd(m, x[i], inv, y);
inv = (inv%x[i]+x[i])%x[i];
res = (res+inv*m*b[i]%fact)%fact; // 解集形式为ans+kt;
}
ans.pb((res+fact)%fact);
}
void dfs(ll now){
if(now==c+1){
CRT();
return;
}
FOR(i, 1, t[now]){
b[now] = k[now][i];
dfs(now+1);
}
return;
}
void sol1(){
dfs(1);
sort(ALL(ans));
for(ll i=0; s; i++){
for(auto val: ans){
if(val+i*fact>0){
cout << val+i*fact << endl;
s--;
if(!s) return;
}
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
while(cin >> c >> s && c && s){
bst = 1;
fact = 1;
ans.clear();
ll tot = 1;
FOR(i, 1, c){
st[i].clear();
cin >> x[i];
cin >> t[i];
FOR(j, 1, t[i]) cin >> k[i][j], st[i].insert(k[i][j]);
if(x[i]*t[bst]>t[i]*x[bst]) bst = i;
tot *= t[i];
fact *= x[i];
}
if(tot<=10000) sol1();
else sol2();
cout << endl;
}
return 0;
}
LightOJ 1356 Prime Independence
如果两个数满足\(a=b\ast prime\)则a与b素因子的个数必定为一奇一偶,所以可以按照每个数素因子个数的奇偶性建立二分图,存在\(a=b\ast prime\)关系的两个数之间连边,用\(HK\)算法求出最大独立集即可。
代码
#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
// 合数分解
const int MAXN=40000;
int prime[MAXN+1];
void getPrime(){
memset(prime, 0 ,sizeof(prime));
for(int i=2; i<=MAXN; i++){
if(!prime[i]) prime[++prime[0]] = i;
for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++){
prime[prime[j]*i] = 1;
if(j%prime[j]==0) break;
}
}
}
ll factor[100][2];
int factCnt, factNum;
int getFactors(ll x){
factCnt = 0;
factNum = 0;
ll temp = x;
for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
factor[factCnt][1] = 0;
if(temp%prime[i]==0){
factor[factCnt][0] = prime[i];
while(temp%prime[i]==0){
factor[factCnt][1]++;
temp /= prime[i];
}
factCnt++;
}
}
if(temp!=1){
factor[factCnt][0] = temp;
factor[factCnt++][1] = 1;
}
FOR(i, 0, factCnt-1) factNum += factor[i][1];
return factCnt;
}
// HK二分图最大匹配 uN为左侧顶点数 G存单向边 顶点编号从0开始 O(sqrt(n)*m)
const int maxn = 40001;
vector<int> G[maxn];
int uN;
int Mx[maxn], My[maxn];
int dx[maxn], dy[maxn];
int dis;
bool used[maxn];
bool searchP(){
queue<int> Q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i=0; i<uN; i++){
if(Mx[i]==-1){
Q.push(i);
dx[i] = 0;
}
}
while(!Q.empty()){
int u = Q.front();
Q.pop();
if(dx[u]>dis) break;
int sz = G[u].size();
for(int i=0; i<sz; i++){
int v = G[u][i];
if(dy[v]==-1){
dy[v] = dx[u]+1;
if(My[v]==-1) dis = dy[v];
else{
dx[My[v]] = dy[v]+1;
Q.push(My[v]);
}
}
}
}
return dis != INF;
}
bool dfs(int u){
int sz = G[u].size();
for(int i=0; i<sz; i++){
int v = G[u][i];
if(!used[v] && dy[v]==dx[u]+1){
used[v] = true;
if(My[v]!=-1 && dy[v]==dis) continue;
if(My[v]==-1 || dfs(My[v])){
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
}
int maxMatch(){
int res = 0;
memset(Mx, -1, sizeof(Mx));
memset(My, -1, sizeof(My));
while(searchP()){
memset(used, false, sizeof(used));
for(int i=0; i<uN; i++){
if(Mx[i]==-1 && dfs(i)){
res++;
}
}
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
getPrime();
int T, _=0;
cin >> T;
while(T--){
int n, cnt=0;
uN = 0;
cin >> n;
vector<int> a(n+1);
map<int, int> mp;
vector<int> lft, ri;
FOR(i, 1, n){
scanf("%d", &a[i]);
}
FOR(i, 1, n){
getFactors(a[i]);
if(factNum%2){
G[uN].clear();
lft.pb(a[i]);
mp[a[i]] = ++uN;
}
else{
mp[a[i]] = ++cnt;
ri.pb(a[i]);
}
}
if(uN){
FOR(i, 0, lft.size()-1){
getFactors(lft[i]);
FOR(j, 0, factCnt-1){
if(mp[lft[i]/factor[j][0]]){
G[i].pb(mp[lft[i]/factor[j][0]]);
}
}
}
}
if(cnt){
FOR(i, 0, ri.size()-1){
getFactors(ri[i]);
FOR(j, 0, factCnt-1){
if(mp[ri[i]/factor[j][0]]){
G[mp[ri[i]/factor[j][0]]-1].pb(i+1);
}
}
}
}
printf("Case %d: %d\n", ++_, n-maxMatch());
}
return 0;
}

浙公网安备 33010602011771号